2 @message |
RecursionError: maximum recursion depth exceeded while calling a Python object
LOG DETAILS:
2025-07-02 04:52:31.196
2025-07-02 04:52:31.197 act = <firebird.qa.plugin.Action object at [hex]>
2025-07-02 04:52:31.197
2025-07-02 04:52:31.197 @pytest.mark.version('>=3')
2025-07-02 04:52:31.197 def test_1(act: Action):
2025-07-02 04:52:31.197 act.expected_stdout = expected_stdout
2025-07-02 04:52:31.197 act.execute()
2025-07-02 04:52:31.197 > assert act.clean_stdout == act.clean_expected_stdout
2025-07-02 04:52:31.197
2025-07-02 04:52:31.197 tests\bugs\core_2969_test.py:1211:
2025-07-02 04:52:31.197 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.197
2025-07-02 04:52:31.197 ops = ('==',), results = (False,)
2025-07-02 04:52:31.197 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 04:52:31.197 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 04:52:31.197
2025-07-02 04:52:31.197 def _call_reprcompare(
2025-07-02 04:52:31.197 ops: Sequence[str],
2025-07-02 04:52:31.197 results: Sequence[bool],
2025-07-02 04:52:31.197 expls: Sequence[str],
2025-07-02 04:52:31.197 each_obj: Sequence[object],
2025-07-02 04:52:31.198 ) -> str:
2025-07-02 04:52:31.198 for i, res, expl in zip(range(len(ops)), results, expls):
2025-07-02 04:52:31.198 try:
2025-07-02 04:52:31.198 done = not res
2025-07-02 04:52:31.198 except Exception:
2025-07-02 04:52:31.198 done = True
2025-07-02 04:52:31.198 if done:
2025-07-02 04:52:31.198 break
2025-07-02 04:52:31.198 if util._reprcompare is not None:
2025-07-02 04:52:31.198 > custom = util._reprcompare(ops[i], each_obj[i], each_obj[i + 1])
2025-07-02 04:52:31.198
2025-07-02 04:52:31.198 C:\Python3x\Lib\site-packages\_pytest\assertion\rewrite.py:499:
2025-07-02 04:52:31.198 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.198
2025-07-02 04:52:31.198 op = '=='
2025-07-02 04:52:31.198 left = 'WAS_OVERWRITTEN CTX_KEY CTX_VAL\n=============== ============================== =======\n1var_... yyy\n1var_997 yyy\n1var_998 yyy\n1var_999 yyy'
2025-07-02 04:52:31.198 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 04:52:31.198
2025-07-02 04:52:31.198 def callbinrepr(op, left: object, right: object) -> Optional[str]:
2025-07-02 04:52:31.198 """Call the pytest_assertrepr_compare hook and prepare the result.
2025-07-02 04:52:31.198
2025-07-02 04:52:31.199 This uses the first result from the hook and then ensures the
2025-07-02 04:52:31.199 following:
2025-07-02 04:52:31.199 * Overly verbose explanations are truncated unless configured otherwise
2025-07-02 04:52:31.199 (eg. if running in verbose mode).
2025-07-02 04:52:31.199 * Embedded newlines are escaped to help util.format_explanation()
2025-07-02 04:52:31.199 later.
2025-07-02 04:52:31.199 * If the rewrite mode is used embedded %-characters are replaced
2025-07-02 04:52:31.199 to protect later % formatting.
2025-07-02 04:52:31.199
2025-07-02 04:52:31.199 The result can be formatted by util.format_explanation() for
2025-07-02 04:52:31.199 pretty printing.
2025-07-02 04:52:31.199 """
2025-07-02 04:52:31.199 > hook_result = ihook.pytest_assertrepr_compare(
2025-07-02 04:52:31.199 config=item.config, op=op, left=left, right=right
2025-07-02 04:52:31.199 )
2025-07-02 04:52:31.199
2025-07-02 04:52:31.199 C:\Python3x\Lib\site-packages\_pytest\assertion\__init__.py:141:
2025-07-02 04:52:31.199 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.199
2025-07-02 04:52:31.199 self = <HookCaller 'pytest_assertrepr_compare'>
2025-07-02 04:52:31.199 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 04:52:31.200 firstresult = False
2025-07-02 04:52:31.200
2025-07-02 04:52:31.200 def __call__(self, **kwargs: object) -> Any:
2025-07-02 04:52:31.200 """Call the hook.
2025-07-02 04:52:31.200
2025-07-02 04:52:31.200 Only accepts keyword arguments, which should match the hook
2025-07-02 04:52:31.200 specification.
2025-07-02 04:52:31.200
2025-07-02 04:52:31.200 Returns the result(s) of calling all registered plugins, see
2025-07-02 04:52:31.200 :ref:`calling`.
2025-07-02 04:52:31.200 """
2025-07-02 04:52:31.200 assert (
2025-07-02 04:52:31.200 not self.is_historic()
2025-07-02 04:52:31.200 ), "Cannot directly call a historic hook - use call_historic instead."
2025-07-02 04:52:31.200 self._verify_all_args_are_provided(kwargs)
2025-07-02 04:52:31.200 firstresult = self.spec.opts.get("firstresult", False) if self.spec else False
2025-07-02 04:52:31.200 # Copy because plugins may register other plugins during iteration (#438).
2025-07-02 04:52:31.200 > return self._hookexec(self.name, self._hookimpls.copy(), kwargs, firstresult)
2025-07-02 04:52:31.200
2025-07-02 04:52:31.200 C:\Python3x\Lib\site-packages\pluggy\_hooks.py:501:
2025-07-02 04:52:31.200 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.201
2025-07-02 04:52:31.201 self = <_pytest.config.PytestPluginManager object at [hex]>
2025-07-02 04:52:31.201 hook_name = 'pytest_assertrepr_compare'
2025-07-02 04:52:31.201 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 04:52:31.201 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 04:52:31.201 firstresult = False
2025-07-02 04:52:31.201
2025-07-02 04:52:31.201 def _hookexec(
2025-07-02 04:52:31.201 self,
2025-07-02 04:52:31.201 hook_name: str,
2025-07-02 04:52:31.201 methods: Sequence[HookImpl],
2025-07-02 04:52:31.201 kwargs: Mapping[str, object],
2025-07-02 04:52:31.201 firstresult: bool,
2025-07-02 04:52:31.201 ) -> object | list[object]:
2025-07-02 04:52:31.201 # called from all hookcaller instances.
2025-07-02 04:52:31.201 # enable_tracing will set its own wrapping function at self._inner_hookexec
2025-07-02 04:52:31.201 > return self._inner_hookexec(hook_name, methods, kwargs, firstresult)
2025-07-02 04:52:31.201
2025-07-02 04:52:31.201 C:\Python3x\Lib\site-packages\pluggy\_manager.py:119:
2025-07-02 04:52:31.201 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.201
2025-07-02 04:52:31.201 config = <_pytest.config.Config object at [hex]>, op = '=='
2025-07-02 04:52:31.202 left = 'WAS_OVERWRITTEN CTX_KEY CTX_VAL\n=============== ============================== =======\n1var_... yyy\n1var_997 yyy\n1var_998 yyy\n1var_999 yyy'
2025-07-02 04:52:31.202 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 04:52:31.202
2025-07-02 04:52:31.202 def pytest_assertrepr_compare(config: Config, op: str, left: object, right: object) -> Optional[List[str]]:
2025-07-02 04:52:31.202 """Returns explanation for comparisons in failing assert expressions.
2025-07-02 04:52:31.202
2025-07-02 04:52:31.202 If both objects are `str`, uses `difflib.ndiff` to provide explanation.
2025-07-02 04:52:31.202 """
2025-07-02 04:52:31.202 if isinstance(left, str) and isinstance(right, str) and op == "==":
2025-07-02 04:52:31.202 # 16.11.2023, pzotov: we have to put empty string at the beginning of each comparing lists.
2025-07-02 04:52:31.202 # Otherwise first diff will be at the same line as 'assert' phrase, which causes readability be poor.
2025-07-02 04:52:31.202 #
2025-07-02 04:52:31.202 left_lines = ['']
2025-07-02 04:52:31.202 left_lines.extend(left.splitlines())
2025-07-02 04:52:31.202 right_lines = ['']
2025-07-02 04:52:31.202 right_lines.extend(right.splitlines())
2025-07-02 04:52:31.202
2025-07-02 04:52:31.202 # 16.11.2023, pzotov
2025-07-02 04:52:31.203 # ndiff output must be interpreted as following:
2025-07-02 04:52:31.203 # * "E - <some text>" ==> MISSED line (it was in EXPECTED text but absent in actual one).
2025-07-02 04:52:31.203 # * "E + <some_text>" ==> EXCESSIVE line (it is not in EXPECTED text but did appear in actual).
2025-07-02 04:52:31.203 # But for QA-purposes, this output must answer the question:
2025-07-02 04:52:31.203 # "what must be changed in ACTUAL output so that it became equal to EXPECTED"
2025-07-02 04:52:31.203 # (i.e. how to "REVERT" actual back to expected).
2025-07-02 04:52:31.203 # In order to see such result, we have to specify 'right_lines' to the 1st argument that is passed to ndiff().
2025-07-02 04:52:31.203 # ::: NB :::
2025-07-02 04:52:31.203 # We assume that all tests are written so that ACTUAL output is left side in 'assert' statement and EXPECTED
2025-07-02 04:52:31.203 # is right side, e.g: assert act.clean_stdout == act.clean_expected_stdout
2025-07-02 04:52:31.203 # This requirement is CRUCIAL if we use ndiff() instead of default pytest comparison method!
2025-07-02 04:52:31.203 #
2025-07-02 04:52:31.203 > return list(ndiff(right_lines, left_lines))
2025-07-02 04:52:31.203
2025-07-02 04:52:31.203 src\firebird\qa\plugin.py:608:
2025-07-02 04:52:31.203 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.203
2025-07-02 04:52:31.203 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.204 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.204 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.204
2025-07-02 04:52:31.204 def compare(self, a, b):
2025-07-02 04:52:31.204 r"""
2025-07-02 04:52:31.204 Compare two sequences of lines; generate the resulting delta.
2025-07-02 04:52:31.204
2025-07-02 04:52:31.204 Each sequence must contain individual single-line strings ending with
2025-07-02 04:52:31.204 newlines. Such sequences can be obtained from the `readlines()` method
2025-07-02 04:52:31.204 of file-like objects. The delta generated also consists of newline-
2025-07-02 04:52:31.204 terminated strings, ready to be printed as-is via the writelines()
2025-07-02 04:52:31.204 method of a file-like object.
2025-07-02 04:52:31.204
2025-07-02 04:52:31.204 Example:
2025-07-02 04:52:31.204
2025-07-02 04:52:31.204 >>> print(''.join(Differ().compare('one\ntwo\nthree\n'.splitlines(True),
2025-07-02 04:52:31.204 ... 'ore\ntree\nemu\n'.splitlines(True))),
2025-07-02 04:52:31.204 ... end="")
2025-07-02 04:52:31.204 - one
2025-07-02 04:52:31.205 + ore
2025-07-02 04:52:31.205 - two
2025-07-02 04:52:31.205 - three
2025-07-02 04:52:31.205 + tree
2025-07-02 04:52:31.205 + emu
2025-07-02 04:52:31.205 """
2025-07-02 04:52:31.205
2025-07-02 04:52:31.205 cruncher = SequenceMatcher(self.linejunk, a, b)
2025-07-02 04:52:31.205 for tag, alo, ahi, blo, bhi in cruncher.get_opcodes():
2025-07-02 04:52:31.205 if tag == 'replace':
2025-07-02 04:52:31.205 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.205 elif tag == 'delete':
2025-07-02 04:52:31.205 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.205 elif tag == 'insert':
2025-07-02 04:52:31.205 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.205 elif tag == 'equal':
2025-07-02 04:52:31.205 g = self._dump(' ', a, alo, ahi)
2025-07-02 04:52:31.205 else:
2025-07-02 04:52:31.205 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.206
2025-07-02 04:52:31.206 > yield from g
2025-07-02 04:52:31.206
2025-07-02 04:52:31.206 C:\Python3x\Lib\difflib.py:872:
2025-07-02 04:52:31.206 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.206
2025-07-02 04:52:31.206 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.206 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.206 alo = 3, ahi = 1101
2025-07-02 04:52:31.206 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.206 blo = 3, bhi = 1101
2025-07-02 04:52:31.206
2025-07-02 04:52:31.206 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.206 r"""
2025-07-02 04:52:31.206 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.206 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.206 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.206 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.206
2025-07-02 04:52:31.206 Example:
2025-07-02 04:52:31.207
2025-07-02 04:52:31.207 >>> d = Differ()
2025-07-02 04:52:31.207 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.207 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.207 >>> print(''.join(results), end="")
2025-07-02 04:52:31.207 - abcDefghiJkl
2025-07-02 04:52:31.207 + abcdefGhijkl
2025-07-02 04:52:31.207 """
2025-07-02 04:52:31.207
2025-07-02 04:52:31.207 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.207 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.207 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.207 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.207 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.207
2025-07-02 04:52:31.207 # search for the pair that matches best without being identical
2025-07-02 04:52:31.207 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.207 # on junk -- unless we have to)
2025-07-02 04:52:31.207 for j in range(blo, bhi):
2025-07-02 04:52:31.208 bj = b[j]
2025-07-02 04:52:31.208 cruncher.set_seq2(bj)
2025-07-02 04:52:31.208 for i in range(alo, ahi):
2025-07-02 04:52:31.208 ai = a[i]
2025-07-02 04:52:31.208 if ai == bj:
2025-07-02 04:52:31.208 if eqi is None:
2025-07-02 04:52:31.208 eqi, eqj = i, j
2025-07-02 04:52:31.208 continue
2025-07-02 04:52:31.208 cruncher.set_seq1(ai)
2025-07-02 04:52:31.208 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.208 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.208 # compares by a factor of 3.
2025-07-02 04:52:31.208 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.208 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.208 # of the computation is cached by cruncher
2025-07-02 04:52:31.208 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.208 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.208 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.208 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.208 if best_ratio < cutoff:
2025-07-02 04:52:31.209 # no non-identical "pretty close" pair
2025-07-02 04:52:31.209 if eqi is None:
2025-07-02 04:52:31.209 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.209 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.209 return
2025-07-02 04:52:31.209 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.209 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.209 else:
2025-07-02 04:52:31.209 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.209 eqi = None
2025-07-02 04:52:31.209
2025-07-02 04:52:31.209 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.209 # identical
2025-07-02 04:52:31.209
2025-07-02 04:52:31.209 # pump out diffs from before the synch point
2025-07-02 04:52:31.209 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.209
2025-07-02 04:52:31.209 # do intraline marking on the synch pair
2025-07-02 04:52:31.209 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.209 if eqi is None:
2025-07-02 04:52:31.209 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.210 atags = btags = ""
2025-07-02 04:52:31.210 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.210 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.210 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.210 if tag == 'replace':
2025-07-02 04:52:31.210 atags += '^' * la
2025-07-02 04:52:31.210 btags += '^' * lb
2025-07-02 04:52:31.210 elif tag == 'delete':
2025-07-02 04:52:31.210 atags += '-' * la
2025-07-02 04:52:31.210 elif tag == 'insert':
2025-07-02 04:52:31.210 btags += '+' * lb
2025-07-02 04:52:31.210 elif tag == 'equal':
2025-07-02 04:52:31.210 atags += ' ' * la
2025-07-02 04:52:31.210 btags += ' ' * lb
2025-07-02 04:52:31.210 else:
2025-07-02 04:52:31.210 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.210 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.210 else:
2025-07-02 04:52:31.210 # the synch pair is identical
2025-07-02 04:52:31.210 yield ' ' + aelt
2025-07-02 04:52:31.210
2025-07-02 04:52:31.211 # pump out diffs from after the synch point
2025-07-02 04:52:31.211 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.211
2025-07-02 04:52:31.211 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.211 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.211
2025-07-02 04:52:31.211 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.211 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.211 alo = 4, ahi = 1101
2025-07-02 04:52:31.211 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.211 blo = 4, bhi = 1101
2025-07-02 04:52:31.211
2025-07-02 04:52:31.211 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.211 g = []
2025-07-02 04:52:31.211 if alo < ahi:
2025-07-02 04:52:31.211 if blo < bhi:
2025-07-02 04:52:31.211 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.211 else:
2025-07-02 04:52:31.212 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.212 elif blo < bhi:
2025-07-02 04:52:31.212 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.212
2025-07-02 04:52:31.212 > yield from g
2025-07-02 04:52:31.212
2025-07-02 04:52:31.212 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.212 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.212
2025-07-02 04:52:31.212 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.212 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.212 alo = 4, ahi = 1101
2025-07-02 04:52:31.212 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.212 blo = 4, bhi = 1101
2025-07-02 04:52:31.212
2025-07-02 04:52:31.212 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.212 r"""
2025-07-02 04:52:31.212 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.212 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.212 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.212 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.213
2025-07-02 04:52:31.213 Example:
2025-07-02 04:52:31.213
2025-07-02 04:52:31.213 >>> d = Differ()
2025-07-02 04:52:31.213 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.213 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.213 >>> print(''.join(results), end="")
2025-07-02 04:52:31.213 - abcDefghiJkl
2025-07-02 04:52:31.213 + abcdefGhijkl
2025-07-02 04:52:31.213 """
2025-07-02 04:52:31.213
2025-07-02 04:52:31.213 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.213 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.213 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.213 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.213 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.213
2025-07-02 04:52:31.213 # search for the pair that matches best without being identical
2025-07-02 04:52:31.213 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.214 # on junk -- unless we have to)
2025-07-02 04:52:31.214 for j in range(blo, bhi):
2025-07-02 04:52:31.214 bj = b[j]
2025-07-02 04:52:31.214 cruncher.set_seq2(bj)
2025-07-02 04:52:31.214 for i in range(alo, ahi):
2025-07-02 04:52:31.214 ai = a[i]
2025-07-02 04:52:31.214 if ai == bj:
2025-07-02 04:52:31.214 if eqi is None:
2025-07-02 04:52:31.214 eqi, eqj = i, j
2025-07-02 04:52:31.214 continue
2025-07-02 04:52:31.214 cruncher.set_seq1(ai)
2025-07-02 04:52:31.214 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.214 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.214 # compares by a factor of 3.
2025-07-02 04:52:31.214 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.214 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.214 # of the computation is cached by cruncher
2025-07-02 04:52:31.214 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.214 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.214 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.215 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.215 if best_ratio < cutoff:
2025-07-02 04:52:31.215 # no non-identical "pretty close" pair
2025-07-02 04:52:31.215 if eqi is None:
2025-07-02 04:52:31.215 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.215 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.215 return
2025-07-02 04:52:31.215 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.215 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.215 else:
2025-07-02 04:52:31.215 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.215 eqi = None
2025-07-02 04:52:31.215
2025-07-02 04:52:31.215 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.215 # identical
2025-07-02 04:52:31.215
2025-07-02 04:52:31.215 # pump out diffs from before the synch point
2025-07-02 04:52:31.215 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.215
2025-07-02 04:52:31.215 # do intraline marking on the synch pair
2025-07-02 04:52:31.215 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.216 if eqi is None:
2025-07-02 04:52:31.216 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.216 atags = btags = ""
2025-07-02 04:52:31.216 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.216 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.216 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.216 if tag == 'replace':
2025-07-02 04:52:31.216 atags += '^' * la
2025-07-02 04:52:31.216 btags += '^' * lb
2025-07-02 04:52:31.216 elif tag == 'delete':
2025-07-02 04:52:31.216 atags += '-' * la
2025-07-02 04:52:31.216 elif tag == 'insert':
2025-07-02 04:52:31.216 btags += '+' * lb
2025-07-02 04:52:31.216 elif tag == 'equal':
2025-07-02 04:52:31.216 atags += ' ' * la
2025-07-02 04:52:31.216 btags += ' ' * lb
2025-07-02 04:52:31.216 else:
2025-07-02 04:52:31.216 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.216 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.216 else:
2025-07-02 04:52:31.216 # the synch pair is identical
2025-07-02 04:52:31.217 yield ' ' + aelt
2025-07-02 04:52:31.217
2025-07-02 04:52:31.217 # pump out diffs from after the synch point
2025-07-02 04:52:31.217 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.217
2025-07-02 04:52:31.217 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.217 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.217
2025-07-02 04:52:31.217 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.217 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.217 alo = 5, ahi = 1101
2025-07-02 04:52:31.217 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.217 blo = 5, bhi = 1101
2025-07-02 04:52:31.217
2025-07-02 04:52:31.217 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.217 g = []
2025-07-02 04:52:31.217 if alo < ahi:
2025-07-02 04:52:31.217 if blo < bhi:
2025-07-02 04:52:31.217 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.217 else:
2025-07-02 04:52:31.218 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.218 elif blo < bhi:
2025-07-02 04:52:31.218 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.218
2025-07-02 04:52:31.218 > yield from g
2025-07-02 04:52:31.218
2025-07-02 04:52:31.218 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.218 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.218
2025-07-02 04:52:31.218 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.218 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.218 alo = 5, ahi = 1101
2025-07-02 04:52:31.218 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.218 blo = 5, bhi = 1101
2025-07-02 04:52:31.218
2025-07-02 04:52:31.218 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.218 r"""
2025-07-02 04:52:31.218 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.218 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.218 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.219 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.219
2025-07-02 04:52:31.219 Example:
2025-07-02 04:52:31.219
2025-07-02 04:52:31.219 >>> d = Differ()
2025-07-02 04:52:31.219 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.219 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.219 >>> print(''.join(results), end="")
2025-07-02 04:52:31.219 - abcDefghiJkl
2025-07-02 04:52:31.219 + abcdefGhijkl
2025-07-02 04:52:31.219 """
2025-07-02 04:52:31.219
2025-07-02 04:52:31.219 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.219 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.219 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.219 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.219 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.220
2025-07-02 04:52:31.220 # search for the pair that matches best without being identical
2025-07-02 04:52:31.220 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.220 # on junk -- unless we have to)
2025-07-02 04:52:31.220 for j in range(blo, bhi):
2025-07-02 04:52:31.220 bj = b[j]
2025-07-02 04:52:31.220 cruncher.set_seq2(bj)
2025-07-02 04:52:31.220 for i in range(alo, ahi):
2025-07-02 04:52:31.220 ai = a[i]
2025-07-02 04:52:31.220 if ai == bj:
2025-07-02 04:52:31.220 if eqi is None:
2025-07-02 04:52:31.220 eqi, eqj = i, j
2025-07-02 04:52:31.220 continue
2025-07-02 04:52:31.220 cruncher.set_seq1(ai)
2025-07-02 04:52:31.220 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.220 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.220 # compares by a factor of 3.
2025-07-02 04:52:31.220 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.220 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.220 # of the computation is cached by cruncher
2025-07-02 04:52:31.221 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.221 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.221 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.221 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.221 if best_ratio < cutoff:
2025-07-02 04:52:31.221 # no non-identical "pretty close" pair
2025-07-02 04:52:31.221 if eqi is None:
2025-07-02 04:52:31.221 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.221 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.221 return
2025-07-02 04:52:31.221 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.221 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.221 else:
2025-07-02 04:52:31.221 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.221 eqi = None
2025-07-02 04:52:31.221
2025-07-02 04:52:31.221 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.221 # identical
2025-07-02 04:52:31.221
2025-07-02 04:52:31.221 # pump out diffs from before the synch point
2025-07-02 04:52:31.221 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.222
2025-07-02 04:52:31.222 # do intraline marking on the synch pair
2025-07-02 04:52:31.222 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.222 if eqi is None:
2025-07-02 04:52:31.222 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.222 atags = btags = ""
2025-07-02 04:52:31.222 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.222 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.222 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.222 if tag == 'replace':
2025-07-02 04:52:31.222 atags += '^' * la
2025-07-02 04:52:31.222 btags += '^' * lb
2025-07-02 04:52:31.222 elif tag == 'delete':
2025-07-02 04:52:31.222 atags += '-' * la
2025-07-02 04:52:31.222 elif tag == 'insert':
2025-07-02 04:52:31.222 btags += '+' * lb
2025-07-02 04:52:31.222 elif tag == 'equal':
2025-07-02 04:52:31.222 atags += ' ' * la
2025-07-02 04:52:31.222 btags += ' ' * lb
2025-07-02 04:52:31.222 else:
2025-07-02 04:52:31.223 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.223 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.223 else:
2025-07-02 04:52:31.223 # the synch pair is identical
2025-07-02 04:52:31.223 yield ' ' + aelt
2025-07-02 04:52:31.223
2025-07-02 04:52:31.223 # pump out diffs from after the synch point
2025-07-02 04:52:31.223 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.223
2025-07-02 04:52:31.223 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.223 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.223
2025-07-02 04:52:31.223 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.223 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.223 alo = 6, ahi = 1101
2025-07-02 04:52:31.223 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.223 blo = 6, bhi = 1101
2025-07-02 04:52:31.223
2025-07-02 04:52:31.223 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.223 g = []
2025-07-02 04:52:31.223 if alo < ahi:
2025-07-02 04:52:31.224 if blo < bhi:
2025-07-02 04:52:31.224 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.224 else:
2025-07-02 04:52:31.224 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.224 elif blo < bhi:
2025-07-02 04:52:31.224 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.224
2025-07-02 04:52:31.224 > yield from g
2025-07-02 04:52:31.224
2025-07-02 04:52:31.224 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.224 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.224
2025-07-02 04:52:31.224 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.224 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.224 alo = 6, ahi = 1101
2025-07-02 04:52:31.224 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.224 blo = 6, bhi = 1101
2025-07-02 04:52:31.224
2025-07-02 04:52:31.224 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.224 r"""
2025-07-02 04:52:31.225 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.225 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.225 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.225 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.225
2025-07-02 04:52:31.225 Example:
2025-07-02 04:52:31.225
2025-07-02 04:52:31.225 >>> d = Differ()
2025-07-02 04:52:31.225 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.225 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.225 >>> print(''.join(results), end="")
2025-07-02 04:52:31.225 - abcDefghiJkl
2025-07-02 04:52:31.225 + abcdefGhijkl
2025-07-02 04:52:31.225 """
2025-07-02 04:52:31.225
2025-07-02 04:52:31.225 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.225 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.225 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.225 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.226 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.226
2025-07-02 04:52:31.226 # search for the pair that matches best without being identical
2025-07-02 04:52:31.226 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.226 # on junk -- unless we have to)
2025-07-02 04:52:31.226 for j in range(blo, bhi):
2025-07-02 04:52:31.226 bj = b[j]
2025-07-02 04:52:31.226 cruncher.set_seq2(bj)
2025-07-02 04:52:31.226 for i in range(alo, ahi):
2025-07-02 04:52:31.226 ai = a[i]
2025-07-02 04:52:31.226 if ai == bj:
2025-07-02 04:52:31.226 if eqi is None:
2025-07-02 04:52:31.226 eqi, eqj = i, j
2025-07-02 04:52:31.226 continue
2025-07-02 04:52:31.226 cruncher.set_seq1(ai)
2025-07-02 04:52:31.226 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.226 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.226 # compares by a factor of 3.
2025-07-02 04:52:31.226 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.226 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.227 # of the computation is cached by cruncher
2025-07-02 04:52:31.227 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.227 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.227 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.227 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.227 if best_ratio < cutoff:
2025-07-02 04:52:31.227 # no non-identical "pretty close" pair
2025-07-02 04:52:31.227 if eqi is None:
2025-07-02 04:52:31.227 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.227 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.227 return
2025-07-02 04:52:31.227 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.227 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.227 else:
2025-07-02 04:52:31.227 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.227 eqi = None
2025-07-02 04:52:31.227
2025-07-02 04:52:31.227 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.227 # identical
2025-07-02 04:52:31.228
2025-07-02 04:52:31.228 # pump out diffs from before the synch point
2025-07-02 04:52:31.228 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.228
2025-07-02 04:52:31.228 # do intraline marking on the synch pair
2025-07-02 04:52:31.228 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.228 if eqi is None:
2025-07-02 04:52:31.228 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.228 atags = btags = ""
2025-07-02 04:52:31.228 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.228 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.228 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.228 if tag == 'replace':
2025-07-02 04:52:31.228 atags += '^' * la
2025-07-02 04:52:31.228 btags += '^' * lb
2025-07-02 04:52:31.228 elif tag == 'delete':
2025-07-02 04:52:31.228 atags += '-' * la
2025-07-02 04:52:31.228 elif tag == 'insert':
2025-07-02 04:52:31.228 btags += '+' * lb
2025-07-02 04:52:31.229 elif tag == 'equal':
2025-07-02 04:52:31.229 atags += ' ' * la
2025-07-02 04:52:31.229 btags += ' ' * lb
2025-07-02 04:52:31.229 else:
2025-07-02 04:52:31.229 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.229 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.229 else:
2025-07-02 04:52:31.229 # the synch pair is identical
2025-07-02 04:52:31.229 yield ' ' + aelt
2025-07-02 04:52:31.229
2025-07-02 04:52:31.229 # pump out diffs from after the synch point
2025-07-02 04:52:31.229 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.229
2025-07-02 04:52:31.229 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.229 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.229
2025-07-02 04:52:31.229 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.229 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.229 alo = 7, ahi = 1101
2025-07-02 04:52:31.229 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.229 blo = 7, bhi = 1101
2025-07-02 04:52:31.230
2025-07-02 04:52:31.230 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.230 g = []
2025-07-02 04:52:31.230 if alo < ahi:
2025-07-02 04:52:31.230 if blo < bhi:
2025-07-02 04:52:31.230 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.230 else:
2025-07-02 04:52:31.230 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.230 elif blo < bhi:
2025-07-02 04:52:31.230 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.230
2025-07-02 04:52:31.230 > yield from g
2025-07-02 04:52:31.230
2025-07-02 04:52:31.230 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.230 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.230
2025-07-02 04:52:31.230 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.230 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.230 alo = 7, ahi = 1101
2025-07-02 04:52:31.230 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.231 blo = 7, bhi = 1101
2025-07-02 04:52:31.231
2025-07-02 04:52:31.231 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.231 r"""
2025-07-02 04:52:31.231 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.231 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.231 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.231 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.231
2025-07-02 04:52:31.231 Example:
2025-07-02 04:52:31.231
2025-07-02 04:52:31.231 >>> d = Differ()
2025-07-02 04:52:31.231 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.231 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.231 >>> print(''.join(results), end="")
2025-07-02 04:52:31.231 - abcDefghiJkl
2025-07-02 04:52:31.231 + abcdefGhijkl
2025-07-02 04:52:31.231 """
2025-07-02 04:52:31.231
2025-07-02 04:52:31.232 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.232 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.232 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.232 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.232 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.232
2025-07-02 04:52:31.232 # search for the pair that matches best without being identical
2025-07-02 04:52:31.232 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.232 # on junk -- unless we have to)
2025-07-02 04:52:31.232 for j in range(blo, bhi):
2025-07-02 04:52:31.232 bj = b[j]
2025-07-02 04:52:31.232 cruncher.set_seq2(bj)
2025-07-02 04:52:31.232 for i in range(alo, ahi):
2025-07-02 04:52:31.232 ai = a[i]
2025-07-02 04:52:31.232 if ai == bj:
2025-07-02 04:52:31.232 if eqi is None:
2025-07-02 04:52:31.232 eqi, eqj = i, j
2025-07-02 04:52:31.232 continue
2025-07-02 04:52:31.232 cruncher.set_seq1(ai)
2025-07-02 04:52:31.232 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.232 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.233 # compares by a factor of 3.
2025-07-02 04:52:31.233 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.233 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.233 # of the computation is cached by cruncher
2025-07-02 04:52:31.233 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.233 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.233 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.233 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.233 if best_ratio < cutoff:
2025-07-02 04:52:31.233 # no non-identical "pretty close" pair
2025-07-02 04:52:31.233 if eqi is None:
2025-07-02 04:52:31.233 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.233 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.233 return
2025-07-02 04:52:31.233 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.233 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.233 else:
2025-07-02 04:52:31.233 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.233 eqi = None
2025-07-02 04:52:31.233
2025-07-02 04:52:31.234 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.234 # identical
2025-07-02 04:52:31.234
2025-07-02 04:52:31.234 # pump out diffs from before the synch point
2025-07-02 04:52:31.234 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.234
2025-07-02 04:52:31.234 # do intraline marking on the synch pair
2025-07-02 04:52:31.234 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.234 if eqi is None:
2025-07-02 04:52:31.234 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.234 atags = btags = ""
2025-07-02 04:52:31.234 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.234 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.234 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.234 if tag == 'replace':
2025-07-02 04:52:31.234 atags += '^' * la
2025-07-02 04:52:31.234 btags += '^' * lb
2025-07-02 04:52:31.234 elif tag == 'delete':
2025-07-02 04:52:31.234 atags += '-' * la
2025-07-02 04:52:31.234 elif tag == 'insert':
2025-07-02 04:52:31.234 btags += '+' * lb
2025-07-02 04:52:31.235 elif tag == 'equal':
2025-07-02 04:52:31.235 atags += ' ' * la
2025-07-02 04:52:31.235 btags += ' ' * lb
2025-07-02 04:52:31.235 else:
2025-07-02 04:52:31.235 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.235 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.235 else:
2025-07-02 04:52:31.235 # the synch pair is identical
2025-07-02 04:52:31.235 yield ' ' + aelt
2025-07-02 04:52:31.235
2025-07-02 04:52:31.235 # pump out diffs from after the synch point
2025-07-02 04:52:31.235 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.235
2025-07-02 04:52:31.235 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.235 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.235
2025-07-02 04:52:31.235 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.235 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.235 alo = 8, ahi = 1101
2025-07-02 04:52:31.235 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.236 blo = 8, bhi = 1101
2025-07-02 04:52:31.236
2025-07-02 04:52:31.236 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.236 g = []
2025-07-02 04:52:31.236 if alo < ahi:
2025-07-02 04:52:31.236 if blo < bhi:
2025-07-02 04:52:31.236 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.236 else:
2025-07-02 04:52:31.236 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.236 elif blo < bhi:
2025-07-02 04:52:31.236 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.236
2025-07-02 04:52:31.236 > yield from g
2025-07-02 04:52:31.236
2025-07-02 04:52:31.236 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.236 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.236
2025-07-02 04:52:31.236 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.236 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.236 alo = 8, ahi = 1101
2025-07-02 04:52:31.237 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.237 blo = 8, bhi = 1101
2025-07-02 04:52:31.237
2025-07-02 04:52:31.237 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.237 r"""
2025-07-02 04:52:31.237 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.237 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.237 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.237 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.237
2025-07-02 04:52:31.237 Example:
2025-07-02 04:52:31.237
2025-07-02 04:52:31.237 >>> d = Differ()
2025-07-02 04:52:31.237 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.237 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.237 >>> print(''.join(results), end="")
2025-07-02 04:52:31.237 - abcDefghiJkl
2025-07-02 04:52:31.237 + abcdefGhijkl
2025-07-02 04:52:31.238 """
2025-07-02 04:52:31.238
2025-07-02 04:52:31.238 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.238 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.238 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.238 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.238 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.238
2025-07-02 04:52:31.238 # search for the pair that matches best without being identical
2025-07-02 04:52:31.238 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.238 # on junk -- unless we have to)
2025-07-02 04:52:31.238 for j in range(blo, bhi):
2025-07-02 04:52:31.238 bj = b[j]
2025-07-02 04:52:31.238 cruncher.set_seq2(bj)
2025-07-02 04:52:31.238 for i in range(alo, ahi):
2025-07-02 04:52:31.238 ai = a[i]
2025-07-02 04:52:31.238 if ai == bj:
2025-07-02 04:52:31.238 if eqi is None:
2025-07-02 04:52:31.238 eqi, eqj = i, j
2025-07-02 04:52:31.238 continue
2025-07-02 04:52:31.238 cruncher.set_seq1(ai)
2025-07-02 04:52:31.239 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.239 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.239 # compares by a factor of 3.
2025-07-02 04:52:31.239 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.239 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.239 # of the computation is cached by cruncher
2025-07-02 04:52:31.239 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.239 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.239 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.239 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.239 if best_ratio < cutoff:
2025-07-02 04:52:31.239 # no non-identical "pretty close" pair
2025-07-02 04:52:31.239 if eqi is None:
2025-07-02 04:52:31.239 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.239 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.239 return
2025-07-02 04:52:31.239 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.239 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.239 else:
2025-07-02 04:52:31.239 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.240 eqi = None
2025-07-02 04:52:31.240
2025-07-02 04:52:31.240 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.240 # identical
2025-07-02 04:52:31.240
2025-07-02 04:52:31.240 # pump out diffs from before the synch point
2025-07-02 04:52:31.240 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.240
2025-07-02 04:52:31.240 # do intraline marking on the synch pair
2025-07-02 04:52:31.240 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.240 if eqi is None:
2025-07-02 04:52:31.240 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.240 atags = btags = ""
2025-07-02 04:52:31.240 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.240 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.240 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.240 if tag == 'replace':
2025-07-02 04:52:31.240 atags += '^' * la
2025-07-02 04:52:31.240 btags += '^' * lb
2025-07-02 04:52:31.240 elif tag == 'delete':
2025-07-02 04:52:31.240 atags += '-' * la
2025-07-02 04:52:31.241 elif tag == 'insert':
2025-07-02 04:52:31.241 btags += '+' * lb
2025-07-02 04:52:31.241 elif tag == 'equal':
2025-07-02 04:52:31.241 atags += ' ' * la
2025-07-02 04:52:31.241 btags += ' ' * lb
2025-07-02 04:52:31.241 else:
2025-07-02 04:52:31.241 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.241 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.241 else:
2025-07-02 04:52:31.241 # the synch pair is identical
2025-07-02 04:52:31.241 yield ' ' + aelt
2025-07-02 04:52:31.241
2025-07-02 04:52:31.241 # pump out diffs from after the synch point
2025-07-02 04:52:31.241 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.241
2025-07-02 04:52:31.241 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.241 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.241
2025-07-02 04:52:31.241 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.241 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.242 alo = 9, ahi = 1101
2025-07-02 04:52:31.242 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.242 blo = 9, bhi = 1101
2025-07-02 04:52:31.242
2025-07-02 04:52:31.242 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.242 g = []
2025-07-02 04:52:31.242 if alo < ahi:
2025-07-02 04:52:31.242 if blo < bhi:
2025-07-02 04:52:31.242 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.242 else:
2025-07-02 04:52:31.242 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.242 elif blo < bhi:
2025-07-02 04:52:31.242 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.242
2025-07-02 04:52:31.242 > yield from g
2025-07-02 04:52:31.242
2025-07-02 04:52:31.242 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.242 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.242
2025-07-02 04:52:31.242 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.242 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.243 alo = 9, ahi = 1101
2025-07-02 04:52:31.243 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.243 blo = 9, bhi = 1101
2025-07-02 04:52:31.243
2025-07-02 04:52:31.243 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.243 r"""
2025-07-02 04:52:31.243 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.243 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.243 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.243 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.243
2025-07-02 04:52:31.243 Example:
2025-07-02 04:52:31.243
2025-07-02 04:52:31.243 >>> d = Differ()
2025-07-02 04:52:31.243 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.243 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.243 >>> print(''.join(results), end="")
2025-07-02 04:52:31.243 - abcDefghiJkl
2025-07-02 04:52:31.243 + abcdefGhijkl
2025-07-02 04:52:31.244 """
2025-07-02 04:52:31.244
2025-07-02 04:52:31.244 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.244 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.244 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.244 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.244 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.244
2025-07-02 04:52:31.244 # search for the pair that matches best without being identical
2025-07-02 04:52:31.244 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.244 # on junk -- unless we have to)
2025-07-02 04:52:31.244 for j in range(blo, bhi):
2025-07-02 04:52:31.244 bj = b[j]
2025-07-02 04:52:31.244 cruncher.set_seq2(bj)
2025-07-02 04:52:31.244 for i in range(alo, ahi):
2025-07-02 04:52:31.244 ai = a[i]
2025-07-02 04:52:31.244 if ai == bj:
2025-07-02 04:52:31.244 if eqi is None:
2025-07-02 04:52:31.244 eqi, eqj = i, j
2025-07-02 04:52:31.244 continue
2025-07-02 04:52:31.245 cruncher.set_seq1(ai)
2025-07-02 04:52:31.245 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.245 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.245 # compares by a factor of 3.
2025-07-02 04:52:31.245 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.245 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.245 # of the computation is cached by cruncher
2025-07-02 04:52:31.245 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.245 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.245 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.245 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.245 if best_ratio < cutoff:
2025-07-02 04:52:31.245 # no non-identical "pretty close" pair
2025-07-02 04:52:31.245 if eqi is None:
2025-07-02 04:52:31.245 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.245 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.245 return
2025-07-02 04:52:31.245 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.245 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.245 else:
2025-07-02 04:52:31.246 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.246 eqi = None
2025-07-02 04:52:31.246
2025-07-02 04:52:31.246 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.246 # identical
2025-07-02 04:52:31.246
2025-07-02 04:52:31.246 # pump out diffs from before the synch point
2025-07-02 04:52:31.246 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.246
2025-07-02 04:52:31.246 # do intraline marking on the synch pair
2025-07-02 04:52:31.246 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.246 if eqi is None:
2025-07-02 04:52:31.246 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.246 atags = btags = ""
2025-07-02 04:52:31.246 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.246 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.246 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.246 if tag == 'replace':
2025-07-02 04:52:31.246 atags += '^' * la
2025-07-02 04:52:31.246 btags += '^' * lb
2025-07-02 04:52:31.247 elif tag == 'delete':
2025-07-02 04:52:31.247 atags += '-' * la
2025-07-02 04:52:31.247 elif tag == 'insert':
2025-07-02 04:52:31.247 btags += '+' * lb
2025-07-02 04:52:31.247 elif tag == 'equal':
2025-07-02 04:52:31.247 atags += ' ' * la
2025-07-02 04:52:31.247 btags += ' ' * lb
2025-07-02 04:52:31.247 else:
2025-07-02 04:52:31.247 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.247 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.247 else:
2025-07-02 04:52:31.247 # the synch pair is identical
2025-07-02 04:52:31.247 yield ' ' + aelt
2025-07-02 04:52:31.247
2025-07-02 04:52:31.247 # pump out diffs from after the synch point
2025-07-02 04:52:31.247 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.247
2025-07-02 04:52:31.247 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.247 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.247
2025-07-02 04:52:31.247 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.248 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.248 alo = 10, ahi = 1101
2025-07-02 04:52:31.248 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.248 blo = 10, bhi = 1101
2025-07-02 04:52:31.248
2025-07-02 04:52:31.248 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.248 g = []
2025-07-02 04:52:31.248 if alo < ahi:
2025-07-02 04:52:31.248 if blo < bhi:
2025-07-02 04:52:31.248 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.248 else:
2025-07-02 04:52:31.248 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.248 elif blo < bhi:
2025-07-02 04:52:31.248 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.248
2025-07-02 04:52:31.248 > yield from g
2025-07-02 04:52:31.248
2025-07-02 04:52:31.248 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.248 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.248
2025-07-02 04:52:31.249 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.249 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.249 alo = 10, ahi = 1101
2025-07-02 04:52:31.249 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.249 blo = 10, bhi = 1101
2025-07-02 04:52:31.249
2025-07-02 04:52:31.249 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.249 r"""
2025-07-02 04:52:31.249 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.249 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.249 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.249 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.249
2025-07-02 04:52:31.249 Example:
2025-07-02 04:52:31.249
2025-07-02 04:52:31.249 >>> d = Differ()
2025-07-02 04:52:31.249 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.249 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.249 >>> print(''.join(results), end="")
2025-07-02 04:52:31.249 - abcDefghiJkl
2025-07-02 04:52:31.250 + abcdefGhijkl
2025-07-02 04:52:31.250 """
2025-07-02 04:52:31.250
2025-07-02 04:52:31.250 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.250 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.250 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.250 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.250 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.250
2025-07-02 04:52:31.250 # search for the pair that matches best without being identical
2025-07-02 04:52:31.250 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.250 # on junk -- unless we have to)
2025-07-02 04:52:31.250 for j in range(blo, bhi):
2025-07-02 04:52:31.250 bj = b[j]
2025-07-02 04:52:31.250 cruncher.set_seq2(bj)
2025-07-02 04:52:31.250 for i in range(alo, ahi):
2025-07-02 04:52:31.250 ai = a[i]
2025-07-02 04:52:31.250 if ai == bj:
2025-07-02 04:52:31.251 if eqi is None:
2025-07-02 04:52:31.251 eqi, eqj = i, j
2025-07-02 04:52:31.251 continue
2025-07-02 04:52:31.251 cruncher.set_seq1(ai)
2025-07-02 04:52:31.251 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.251 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.251 # compares by a factor of 3.
2025-07-02 04:52:31.251 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.251 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.251 # of the computation is cached by cruncher
2025-07-02 04:52:31.251 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.251 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.251 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.251 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.251 if best_ratio < cutoff:
2025-07-02 04:52:31.251 # no non-identical "pretty close" pair
2025-07-02 04:52:31.251 if eqi is None:
2025-07-02 04:52:31.251 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.251 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.251 return
2025-07-02 04:52:31.251 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.252 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.252 else:
2025-07-02 04:52:31.252 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.252 eqi = None
2025-07-02 04:52:31.252
2025-07-02 04:52:31.252 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.252 # identical
2025-07-02 04:52:31.252
2025-07-02 04:52:31.252 # pump out diffs from before the synch point
2025-07-02 04:52:31.252 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.252
2025-07-02 04:52:31.252 # do intraline marking on the synch pair
2025-07-02 04:52:31.252 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.252 if eqi is None:
2025-07-02 04:52:31.252 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.252 atags = btags = ""
2025-07-02 04:52:31.252 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.252 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.252 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.252 if tag == 'replace':
2025-07-02 04:52:31.252 atags += '^' * la
2025-07-02 04:52:31.253 btags += '^' * lb
2025-07-02 04:52:31.253 elif tag == 'delete':
2025-07-02 04:52:31.253 atags += '-' * la
2025-07-02 04:52:31.253 elif tag == 'insert':
2025-07-02 04:52:31.253 btags += '+' * lb
2025-07-02 04:52:31.253 elif tag == 'equal':
2025-07-02 04:52:31.253 atags += ' ' * la
2025-07-02 04:52:31.253 btags += ' ' * lb
2025-07-02 04:52:31.253 else:
2025-07-02 04:52:31.253 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.253 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.253 else:
2025-07-02 04:52:31.253 # the synch pair is identical
2025-07-02 04:52:31.253 yield ' ' + aelt
2025-07-02 04:52:31.253
2025-07-02 04:52:31.253 # pump out diffs from after the synch point
2025-07-02 04:52:31.253 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.253
2025-07-02 04:52:31.253 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.253 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.253
2025-07-02 04:52:31.254 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.254 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.254 alo = 11, ahi = 1101
2025-07-02 04:52:31.254 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.254 blo = 11, bhi = 1101
2025-07-02 04:52:31.254
2025-07-02 04:52:31.254 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.254 g = []
2025-07-02 04:52:31.254 if alo < ahi:
2025-07-02 04:52:31.254 if blo < bhi:
2025-07-02 04:52:31.254 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.254 else:
2025-07-02 04:52:31.254 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.254 elif blo < bhi:
2025-07-02 04:52:31.254 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.254
2025-07-02 04:52:31.254 > yield from g
2025-07-02 04:52:31.254
2025-07-02 04:52:31.254 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.254 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.255
2025-07-02 04:52:31.255 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.255 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.255 alo = 11, ahi = 1101
2025-07-02 04:52:31.255 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.255 blo = 11, bhi = 1101
2025-07-02 04:52:31.255
2025-07-02 04:52:31.255 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.255 r"""
2025-07-02 04:52:31.255 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.255 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.255 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.255 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.255
2025-07-02 04:52:31.255 Example:
2025-07-02 04:52:31.255
2025-07-02 04:52:31.255 >>> d = Differ()
2025-07-02 04:52:31.255 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.255 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.255 >>> print(''.join(results), end="")
2025-07-02 04:52:31.256 - abcDefghiJkl
2025-07-02 04:52:31.256 + abcdefGhijkl
2025-07-02 04:52:31.256 """
2025-07-02 04:52:31.256
2025-07-02 04:52:31.256 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.256 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.256 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.256 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.256 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.256
2025-07-02 04:52:31.256 # search for the pair that matches best without being identical
2025-07-02 04:52:31.256 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.256 # on junk -- unless we have to)
2025-07-02 04:52:31.256 for j in range(blo, bhi):
2025-07-02 04:52:31.256 bj = b[j]
2025-07-02 04:52:31.256 cruncher.set_seq2(bj)
2025-07-02 04:52:31.256 for i in range(alo, ahi):
2025-07-02 04:52:31.256 ai = a[i]
2025-07-02 04:52:31.256 if ai == bj:
2025-07-02 04:52:31.256 if eqi is None:
2025-07-02 04:52:31.257 eqi, eqj = i, j
2025-07-02 04:52:31.257 continue
2025-07-02 04:52:31.257 cruncher.set_seq1(ai)
2025-07-02 04:52:31.257 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.257 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.257 # compares by a factor of 3.
2025-07-02 04:52:31.257 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.257 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.257 # of the computation is cached by cruncher
2025-07-02 04:52:31.257 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.257 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.257 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.257 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.257 if best_ratio < cutoff:
2025-07-02 04:52:31.257 # no non-identical "pretty close" pair
2025-07-02 04:52:31.257 if eqi is None:
2025-07-02 04:52:31.257 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.257 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.257 return
2025-07-02 04:52:31.257 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.257 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.258 else:
2025-07-02 04:52:31.258 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.258 eqi = None
2025-07-02 04:52:31.258
2025-07-02 04:52:31.258 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.258 # identical
2025-07-02 04:52:31.258
2025-07-02 04:52:31.258 # pump out diffs from before the synch point
2025-07-02 04:52:31.258 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.258
2025-07-02 04:52:31.258 # do intraline marking on the synch pair
2025-07-02 04:52:31.258 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.258 if eqi is None:
2025-07-02 04:52:31.258 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.258 atags = btags = ""
2025-07-02 04:52:31.258 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.258 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.258 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.258 if tag == 'replace':
2025-07-02 04:52:31.258 atags += '^' * la
2025-07-02 04:52:31.258 btags += '^' * lb
2025-07-02 04:52:31.258 elif tag == 'delete':
2025-07-02 04:52:31.259 atags += '-' * la
2025-07-02 04:52:31.259 elif tag == 'insert':
2025-07-02 04:52:31.259 btags += '+' * lb
2025-07-02 04:52:31.259 elif tag == 'equal':
2025-07-02 04:52:31.259 atags += ' ' * la
2025-07-02 04:52:31.259 btags += ' ' * lb
2025-07-02 04:52:31.259 else:
2025-07-02 04:52:31.259 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.259 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.259 else:
2025-07-02 04:52:31.259 # the synch pair is identical
2025-07-02 04:52:31.259 yield ' ' + aelt
2025-07-02 04:52:31.259
2025-07-02 04:52:31.259 # pump out diffs from after the synch point
2025-07-02 04:52:31.259 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.259
2025-07-02 04:52:31.259 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.259 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.259
2025-07-02 04:52:31.259 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.259 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.260 alo = 12, ahi = 1101
2025-07-02 04:52:31.260 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.260 blo = 12, bhi = 1101
2025-07-02 04:52:31.260
2025-07-02 04:52:31.260 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.260 g = []
2025-07-02 04:52:31.260 if alo < ahi:
2025-07-02 04:52:31.260 if blo < bhi:
2025-07-02 04:52:31.260 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.260 else:
2025-07-02 04:52:31.260 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.260 elif blo < bhi:
2025-07-02 04:52:31.260 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.260
2025-07-02 04:52:31.260 > yield from g
2025-07-02 04:52:31.260
2025-07-02 04:52:31.260 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.260 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.260
2025-07-02 04:52:31.260 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.260 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.261 alo = 12, ahi = 1101
2025-07-02 04:52:31.261 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.261 blo = 12, bhi = 1101
2025-07-02 04:52:31.261
2025-07-02 04:52:31.261 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.261 r"""
2025-07-02 04:52:31.261 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.261 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.261 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.261 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.261
2025-07-02 04:52:31.261 Example:
2025-07-02 04:52:31.261
2025-07-02 04:52:31.261 >>> d = Differ()
2025-07-02 04:52:31.261 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.261 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.261 >>> print(''.join(results), end="")
2025-07-02 04:52:31.261 - abcDefghiJkl
2025-07-02 04:52:31.261 + abcdefGhijkl
2025-07-02 04:52:31.262 """
2025-07-02 04:52:31.262
2025-07-02 04:52:31.262 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.262 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.262 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.262 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.262 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.262
2025-07-02 04:52:31.262 # search for the pair that matches best without being identical
2025-07-02 04:52:31.262 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.262 # on junk -- unless we have to)
2025-07-02 04:52:31.262 for j in range(blo, bhi):
2025-07-02 04:52:31.262 bj = b[j]
2025-07-02 04:52:31.262 cruncher.set_seq2(bj)
2025-07-02 04:52:31.262 for i in range(alo, ahi):
2025-07-02 04:52:31.262 ai = a[i]
2025-07-02 04:52:31.262 if ai == bj:
2025-07-02 04:52:31.262 if eqi is None:
2025-07-02 04:52:31.262 eqi, eqj = i, j
2025-07-02 04:52:31.262 continue
2025-07-02 04:52:31.263 cruncher.set_seq1(ai)
2025-07-02 04:52:31.263 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.263 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.263 # compares by a factor of 3.
2025-07-02 04:52:31.263 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.263 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.263 # of the computation is cached by cruncher
2025-07-02 04:52:31.263 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.263 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.263 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.263 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.263 if best_ratio < cutoff:
2025-07-02 04:52:31.263 # no non-identical "pretty close" pair
2025-07-02 04:52:31.263 if eqi is None:
2025-07-02 04:52:31.263 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.263 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.263 return
2025-07-02 04:52:31.263 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.263 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.263 else:
2025-07-02 04:52:31.263 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.264 eqi = None
2025-07-02 04:52:31.264
2025-07-02 04:52:31.264 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.264 # identical
2025-07-02 04:52:31.264
2025-07-02 04:52:31.264 # pump out diffs from before the synch point
2025-07-02 04:52:31.264 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.264
2025-07-02 04:52:31.264 # do intraline marking on the synch pair
2025-07-02 04:52:31.264 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.264 if eqi is None:
2025-07-02 04:52:31.264 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.264 atags = btags = ""
2025-07-02 04:52:31.264 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.264 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.264 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.264 if tag == 'replace':
2025-07-02 04:52:31.264 atags += '^' * la
2025-07-02 04:52:31.264 btags += '^' * lb
2025-07-02 04:52:31.264 elif tag == 'delete':
2025-07-02 04:52:31.264 atags += '-' * la
2025-07-02 04:52:31.264 elif tag == 'insert':
2025-07-02 04:52:31.265 btags += '+' * lb
2025-07-02 04:52:31.265 elif tag == 'equal':
2025-07-02 04:52:31.265 atags += ' ' * la
2025-07-02 04:52:31.265 btags += ' ' * lb
2025-07-02 04:52:31.265 else:
2025-07-02 04:52:31.265 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.265 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.265 else:
2025-07-02 04:52:31.265 # the synch pair is identical
2025-07-02 04:52:31.265 yield ' ' + aelt
2025-07-02 04:52:31.265
2025-07-02 04:52:31.265 # pump out diffs from after the synch point
2025-07-02 04:52:31.265 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.265
2025-07-02 04:52:31.265 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.265 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.265
2025-07-02 04:52:31.265 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.265 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.265 alo = 13, ahi = 1101
2025-07-02 04:52:31.265 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.266 blo = 13, bhi = 1101
2025-07-02 04:52:31.266
2025-07-02 04:52:31.266 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.266 g = []
2025-07-02 04:52:31.266 if alo < ahi:
2025-07-02 04:52:31.266 if blo < bhi:
2025-07-02 04:52:31.266 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.266 else:
2025-07-02 04:52:31.266 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.266 elif blo < bhi:
2025-07-02 04:52:31.266 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.266
2025-07-02 04:52:31.266 > yield from g
2025-07-02 04:52:31.266
2025-07-02 04:52:31.266 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.266 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.266
2025-07-02 04:52:31.266 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.266 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.267 alo = 13, ahi = 1101
2025-07-02 04:52:31.267 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.267 blo = 13, bhi = 1101
2025-07-02 04:52:31.267
2025-07-02 04:52:31.267 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.267 r"""
2025-07-02 04:52:31.267 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.267 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.267 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.267 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.267
2025-07-02 04:52:31.267 Example:
2025-07-02 04:52:31.267
2025-07-02 04:52:31.267 >>> d = Differ()
2025-07-02 04:52:31.267 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.267 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.267 >>> print(''.join(results), end="")
2025-07-02 04:52:31.267 - abcDefghiJkl
2025-07-02 04:52:31.267 + abcdefGhijkl
2025-07-02 04:52:31.268 """
2025-07-02 04:52:31.268
2025-07-02 04:52:31.268 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.268 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.268 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.268 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.268 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.268
2025-07-02 04:52:31.268 # search for the pair that matches best without being identical
2025-07-02 04:52:31.268 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.268 # on junk -- unless we have to)
2025-07-02 04:52:31.268 for j in range(blo, bhi):
2025-07-02 04:52:31.268 bj = b[j]
2025-07-02 04:52:31.268 cruncher.set_seq2(bj)
2025-07-02 04:52:31.268 for i in range(alo, ahi):
2025-07-02 04:52:31.268 ai = a[i]
2025-07-02 04:52:31.268 if ai == bj:
2025-07-02 04:52:31.268 if eqi is None:
2025-07-02 04:52:31.268 eqi, eqj = i, j
2025-07-02 04:52:31.268 continue
2025-07-02 04:52:31.268 cruncher.set_seq1(ai)
2025-07-02 04:52:31.269 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.269 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.269 # compares by a factor of 3.
2025-07-02 04:52:31.269 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.269 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.269 # of the computation is cached by cruncher
2025-07-02 04:52:31.269 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.269 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.269 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.269 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.269 if best_ratio < cutoff:
2025-07-02 04:52:31.269 # no non-identical "pretty close" pair
2025-07-02 04:52:31.269 if eqi is None:
2025-07-02 04:52:31.269 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.269 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.269 return
2025-07-02 04:52:31.269 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.269 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.269 else:
2025-07-02 04:52:31.269 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.270 eqi = None
2025-07-02 04:52:31.270
2025-07-02 04:52:31.270 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.270 # identical
2025-07-02 04:52:31.270
2025-07-02 04:52:31.270 # pump out diffs from before the synch point
2025-07-02 04:52:31.270 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.270
2025-07-02 04:52:31.270 # do intraline marking on the synch pair
2025-07-02 04:52:31.270 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.270 if eqi is None:
2025-07-02 04:52:31.270 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.270 atags = btags = ""
2025-07-02 04:52:31.270 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.270 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.270 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.270 if tag == 'replace':
2025-07-02 04:52:31.270 atags += '^' * la
2025-07-02 04:52:31.270 btags += '^' * lb
2025-07-02 04:52:31.271 elif tag == 'delete':
2025-07-02 04:52:31.271 atags += '-' * la
2025-07-02 04:52:31.271 elif tag == 'insert':
2025-07-02 04:52:31.271 btags += '+' * lb
2025-07-02 04:52:31.271 elif tag == 'equal':
2025-07-02 04:52:31.271 atags += ' ' * la
2025-07-02 04:52:31.271 btags += ' ' * lb
2025-07-02 04:52:31.271 else:
2025-07-02 04:52:31.271 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.271 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.271 else:
2025-07-02 04:52:31.271 # the synch pair is identical
2025-07-02 04:52:31.271 yield ' ' + aelt
2025-07-02 04:52:31.271
2025-07-02 04:52:31.271 # pump out diffs from after the synch point
2025-07-02 04:52:31.271 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.271
2025-07-02 04:52:31.271 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.271 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.271
2025-07-02 04:52:31.271 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.272 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.272 alo = 14, ahi = 1101
2025-07-02 04:52:31.272 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.272 blo = 14, bhi = 1101
2025-07-02 04:52:31.272
2025-07-02 04:52:31.272 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.272 g = []
2025-07-02 04:52:31.272 if alo < ahi:
2025-07-02 04:52:31.272 if blo < bhi:
2025-07-02 04:52:31.272 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.272 else:
2025-07-02 04:52:31.272 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.272 elif blo < bhi:
2025-07-02 04:52:31.272 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.272
2025-07-02 04:52:31.272 > yield from g
2025-07-02 04:52:31.272
2025-07-02 04:52:31.272 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.272 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.272
2025-07-02 04:52:31.273 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.273 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.273 alo = 14, ahi = 1101
2025-07-02 04:52:31.273 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.273 blo = 14, bhi = 1101
2025-07-02 04:52:31.273
2025-07-02 04:52:31.273 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.273 r"""
2025-07-02 04:52:31.273 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.273 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.273 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.273 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.273
2025-07-02 04:52:31.273 Example:
2025-07-02 04:52:31.273
2025-07-02 04:52:31.273 >>> d = Differ()
2025-07-02 04:52:31.273 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.273 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.273 >>> print(''.join(results), end="")
2025-07-02 04:52:31.273 - abcDefghiJkl
2025-07-02 04:52:31.274 + abcdefGhijkl
2025-07-02 04:52:31.274 """
2025-07-02 04:52:31.274
2025-07-02 04:52:31.274 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.274 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.274 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.274 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.274 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.274
2025-07-02 04:52:31.274 # search for the pair that matches best without being identical
2025-07-02 04:52:31.274 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.274 # on junk -- unless we have to)
2025-07-02 04:52:31.274 for j in range(blo, bhi):
2025-07-02 04:52:31.274 bj = b[j]
2025-07-02 04:52:31.274 cruncher.set_seq2(bj)
2025-07-02 04:52:31.274 for i in range(alo, ahi):
2025-07-02 04:52:31.274 ai = a[i]
2025-07-02 04:52:31.274 if ai == bj:
2025-07-02 04:52:31.274 if eqi is None:
2025-07-02 04:52:31.275 eqi, eqj = i, j
2025-07-02 04:52:31.275 continue
2025-07-02 04:52:31.275 cruncher.set_seq1(ai)
2025-07-02 04:52:31.275 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.275 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.275 # compares by a factor of 3.
2025-07-02 04:52:31.275 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.275 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.275 # of the computation is cached by cruncher
2025-07-02 04:52:31.275 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.275 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.275 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.275 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.275 if best_ratio < cutoff:
2025-07-02 04:52:31.275 # no non-identical "pretty close" pair
2025-07-02 04:52:31.275 if eqi is None:
2025-07-02 04:52:31.275 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.275 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.275 return
2025-07-02 04:52:31.275 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.276 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.276 else:
2025-07-02 04:52:31.276 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.276 eqi = None
2025-07-02 04:52:31.276
2025-07-02 04:52:31.276 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.276 # identical
2025-07-02 04:52:31.276
2025-07-02 04:52:31.276 # pump out diffs from before the synch point
2025-07-02 04:52:31.276 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.276
2025-07-02 04:52:31.276 # do intraline marking on the synch pair
2025-07-02 04:52:31.276 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.276 if eqi is None:
2025-07-02 04:52:31.276 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.276 atags = btags = ""
2025-07-02 04:52:31.276 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.276 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.276 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.276 if tag == 'replace':
2025-07-02 04:52:31.276 atags += '^' * la
2025-07-02 04:52:31.277 btags += '^' * lb
2025-07-02 04:52:31.277 elif tag == 'delete':
2025-07-02 04:52:31.277 atags += '-' * la
2025-07-02 04:52:31.277 elif tag == 'insert':
2025-07-02 04:52:31.277 btags += '+' * lb
2025-07-02 04:52:31.277 elif tag == 'equal':
2025-07-02 04:52:31.277 atags += ' ' * la
2025-07-02 04:52:31.277 btags += ' ' * lb
2025-07-02 04:52:31.277 else:
2025-07-02 04:52:31.277 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.277 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.277 else:
2025-07-02 04:52:31.277 # the synch pair is identical
2025-07-02 04:52:31.277 yield ' ' + aelt
2025-07-02 04:52:31.277
2025-07-02 04:52:31.277 # pump out diffs from after the synch point
2025-07-02 04:52:31.277 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.277
2025-07-02 04:52:31.277 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.277 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.277
2025-07-02 04:52:31.278 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.278 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.278 alo = 15, ahi = 1101
2025-07-02 04:52:31.278 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.278 blo = 15, bhi = 1101
2025-07-02 04:52:31.278
2025-07-02 04:52:31.278 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.278 g = []
2025-07-02 04:52:31.278 if alo < ahi:
2025-07-02 04:52:31.278 if blo < bhi:
2025-07-02 04:52:31.278 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.278 else:
2025-07-02 04:52:31.278 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.278 elif blo < bhi:
2025-07-02 04:52:31.278 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.278
2025-07-02 04:52:31.278 > yield from g
2025-07-02 04:52:31.278
2025-07-02 04:52:31.278 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.279 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.279
2025-07-02 04:52:31.279 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.279 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.279 alo = 15, ahi = 1101
2025-07-02 04:52:31.279 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.279 blo = 15, bhi = 1101
2025-07-02 04:52:31.279
2025-07-02 04:52:31.279 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.279 r"""
2025-07-02 04:52:31.279 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.279 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.279 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.279 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.279
2025-07-02 04:52:31.279 Example:
2025-07-02 04:52:31.279
2025-07-02 04:52:31.279 >>> d = Differ()
2025-07-02 04:52:31.279 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.279 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.280 >>> print(''.join(results), end="")
2025-07-02 04:52:31.280 - abcDefghiJkl
2025-07-02 04:52:31.280 + abcdefGhijkl
2025-07-02 04:52:31.280 """
2025-07-02 04:52:31.280
2025-07-02 04:52:31.280 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.280 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.280 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.280 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.280 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.280
2025-07-02 04:52:31.280 # search for the pair that matches best without being identical
2025-07-02 04:52:31.280 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.280 # on junk -- unless we have to)
2025-07-02 04:52:31.280 for j in range(blo, bhi):
2025-07-02 04:52:31.280 bj = b[j]
2025-07-02 04:52:31.280 cruncher.set_seq2(bj)
2025-07-02 04:52:31.280 for i in range(alo, ahi):
2025-07-02 04:52:31.280 ai = a[i]
2025-07-02 04:52:31.281 if ai == bj:
2025-07-02 04:52:31.281 if eqi is None:
2025-07-02 04:52:31.281 eqi, eqj = i, j
2025-07-02 04:52:31.281 continue
2025-07-02 04:52:31.281 cruncher.set_seq1(ai)
2025-07-02 04:52:31.281 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.281 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.281 # compares by a factor of 3.
2025-07-02 04:52:31.281 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.281 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.281 # of the computation is cached by cruncher
2025-07-02 04:52:31.281 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.281 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.281 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.281 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.281 if best_ratio < cutoff:
2025-07-02 04:52:31.281 # no non-identical "pretty close" pair
2025-07-02 04:52:31.281 if eqi is None:
2025-07-02 04:52:31.281 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.281 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.282 return
2025-07-02 04:52:31.282 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.282 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.282 else:
2025-07-02 04:52:31.282 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.282 eqi = None
2025-07-02 04:52:31.282
2025-07-02 04:52:31.282 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.282 # identical
2025-07-02 04:52:31.282
2025-07-02 04:52:31.282 # pump out diffs from before the synch point
2025-07-02 04:52:31.282 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.282
2025-07-02 04:52:31.282 # do intraline marking on the synch pair
2025-07-02 04:52:31.282 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.282 if eqi is None:
2025-07-02 04:52:31.282 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.282 atags = btags = ""
2025-07-02 04:52:31.282 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.282 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.282 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.283 if tag == 'replace':
2025-07-02 04:52:31.283 atags += '^' * la
2025-07-02 04:52:31.283 btags += '^' * lb
2025-07-02 04:52:31.283 elif tag == 'delete':
2025-07-02 04:52:31.283 atags += '-' * la
2025-07-02 04:52:31.283 elif tag == 'insert':
2025-07-02 04:52:31.283 btags += '+' * lb
2025-07-02 04:52:31.283 elif tag == 'equal':
2025-07-02 04:52:31.283 atags += ' ' * la
2025-07-02 04:52:31.283 btags += ' ' * lb
2025-07-02 04:52:31.283 else:
2025-07-02 04:52:31.283 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.283 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.283 else:
2025-07-02 04:52:31.283 # the synch pair is identical
2025-07-02 04:52:31.283 yield ' ' + aelt
2025-07-02 04:52:31.283
2025-07-02 04:52:31.283 # pump out diffs from after the synch point
2025-07-02 04:52:31.283 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.283
2025-07-02 04:52:31.283 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.284 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.284
2025-07-02 04:52:31.284 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.284 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.284 alo = 16, ahi = 1101
2025-07-02 04:52:31.284 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.284 blo = 16, bhi = 1101
2025-07-02 04:52:31.284
2025-07-02 04:52:31.284 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.284 g = []
2025-07-02 04:52:31.284 if alo < ahi:
2025-07-02 04:52:31.284 if blo < bhi:
2025-07-02 04:52:31.284 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.284 else:
2025-07-02 04:52:31.284 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.284 elif blo < bhi:
2025-07-02 04:52:31.284 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.284
2025-07-02 04:52:31.284 > yield from g
2025-07-02 04:52:31.284
2025-07-02 04:52:31.284 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.285 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.285
2025-07-02 04:52:31.285 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.285 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.285 alo = 16, ahi = 1101
2025-07-02 04:52:31.285 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.285 blo = 16, bhi = 1101
2025-07-02 04:52:31.285
2025-07-02 04:52:31.285 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.285 r"""
2025-07-02 04:52:31.285 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.285 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.285 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.285 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.285
2025-07-02 04:52:31.285 Example:
2025-07-02 04:52:31.285
2025-07-02 04:52:31.285 >>> d = Differ()
2025-07-02 04:52:31.285 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.285 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.285 >>> print(''.join(results), end="")
2025-07-02 04:52:31.286 - abcDefghiJkl
2025-07-02 04:52:31.286 + abcdefGhijkl
2025-07-02 04:52:31.286 """
2025-07-02 04:52:31.286
2025-07-02 04:52:31.286 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.286 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.286 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.286 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.286 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.286
2025-07-02 04:52:31.286 # search for the pair that matches best without being identical
2025-07-02 04:52:31.286 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.286 # on junk -- unless we have to)
2025-07-02 04:52:31.286 for j in range(blo, bhi):
2025-07-02 04:52:31.286 bj = b[j]
2025-07-02 04:52:31.286 cruncher.set_seq2(bj)
2025-07-02 04:52:31.286 for i in range(alo, ahi):
2025-07-02 04:52:31.286 ai = a[i]
2025-07-02 04:52:31.286 if ai == bj:
2025-07-02 04:52:31.286 if eqi is None:
2025-07-02 04:52:31.287 eqi, eqj = i, j
2025-07-02 04:52:31.287 continue
2025-07-02 04:52:31.287 cruncher.set_seq1(ai)
2025-07-02 04:52:31.287 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.287 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.287 # compares by a factor of 3.
2025-07-02 04:52:31.287 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.287 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.287 # of the computation is cached by cruncher
2025-07-02 04:52:31.287 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.287 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.287 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.287 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.287 if best_ratio < cutoff:
2025-07-02 04:52:31.287 # no non-identical "pretty close" pair
2025-07-02 04:52:31.287 if eqi is None:
2025-07-02 04:52:31.287 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.287 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.288 return
2025-07-02 04:52:31.288 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.288 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.288 else:
2025-07-02 04:52:31.288 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.288 eqi = None
2025-07-02 04:52:31.288
2025-07-02 04:52:31.288 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.288 # identical
2025-07-02 04:52:31.288
2025-07-02 04:52:31.288 # pump out diffs from before the synch point
2025-07-02 04:52:31.288 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.288
2025-07-02 04:52:31.288 # do intraline marking on the synch pair
2025-07-02 04:52:31.288 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.288 if eqi is None:
2025-07-02 04:52:31.288 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.288 atags = btags = ""
2025-07-02 04:52:31.288 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.288 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.288 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.289 if tag == 'replace':
2025-07-02 04:52:31.289 atags += '^' * la
2025-07-02 04:52:31.289 btags += '^' * lb
2025-07-02 04:52:31.289 elif tag == 'delete':
2025-07-02 04:52:31.289 atags += '-' * la
2025-07-02 04:52:31.289 elif tag == 'insert':
2025-07-02 04:52:31.289 btags += '+' * lb
2025-07-02 04:52:31.289 elif tag == 'equal':
2025-07-02 04:52:31.289 atags += ' ' * la
2025-07-02 04:52:31.289 btags += ' ' * lb
2025-07-02 04:52:31.289 else:
2025-07-02 04:52:31.289 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.289 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.289 else:
2025-07-02 04:52:31.289 # the synch pair is identical
2025-07-02 04:52:31.289 yield ' ' + aelt
2025-07-02 04:52:31.289
2025-07-02 04:52:31.289 # pump out diffs from after the synch point
2025-07-02 04:52:31.289 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.289
2025-07-02 04:52:31.290 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.290 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.290
2025-07-02 04:52:31.290 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.290 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.290 alo = 17, ahi = 1101
2025-07-02 04:52:31.290 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.290 blo = 17, bhi = 1101
2025-07-02 04:52:31.290
2025-07-02 04:52:31.290 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.290 g = []
2025-07-02 04:52:31.290 if alo < ahi:
2025-07-02 04:52:31.290 if blo < bhi:
2025-07-02 04:52:31.290 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.290 else:
2025-07-02 04:52:31.290 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.290 elif blo < bhi:
2025-07-02 04:52:31.290 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.290
2025-07-02 04:52:31.290 > yield from g
2025-07-02 04:52:31.290
2025-07-02 04:52:31.291 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.291 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.291
2025-07-02 04:52:31.291 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.291 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.291 alo = 17, ahi = 1101
2025-07-02 04:52:31.291 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.291 blo = 17, bhi = 1101
2025-07-02 04:52:31.291
2025-07-02 04:52:31.291 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.291 r"""
2025-07-02 04:52:31.291 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.291 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.291 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.291 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.291
2025-07-02 04:52:31.291 Example:
2025-07-02 04:52:31.291
2025-07-02 04:52:31.291 >>> d = Differ()
2025-07-02 04:52:31.291 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.292 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.292 >>> print(''.join(results), end="")
2025-07-02 04:52:31.292 - abcDefghiJkl
2025-07-02 04:52:31.292 + abcdefGhijkl
2025-07-02 04:52:31.292 """
2025-07-02 04:52:31.292
2025-07-02 04:52:31.292 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.292 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.292 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.292 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.292 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.292
2025-07-02 04:52:31.292 # search for the pair that matches best without being identical
2025-07-02 04:52:31.292 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.292 # on junk -- unless we have to)
2025-07-02 04:52:31.292 for j in range(blo, bhi):
2025-07-02 04:52:31.292 bj = b[j]
2025-07-02 04:52:31.292 cruncher.set_seq2(bj)
2025-07-02 04:52:31.292 for i in range(alo, ahi):
2025-07-02 04:52:31.293 ai = a[i]
2025-07-02 04:52:31.293 if ai == bj:
2025-07-02 04:52:31.293 if eqi is None:
2025-07-02 04:52:31.293 eqi, eqj = i, j
2025-07-02 04:52:31.293 continue
2025-07-02 04:52:31.293 cruncher.set_seq1(ai)
2025-07-02 04:52:31.293 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.293 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.293 # compares by a factor of 3.
2025-07-02 04:52:31.293 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.293 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.293 # of the computation is cached by cruncher
2025-07-02 04:52:31.293 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.293 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.293 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.293 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.293 if best_ratio < cutoff:
2025-07-02 04:52:31.293 # no non-identical "pretty close" pair
2025-07-02 04:52:31.293 if eqi is None:
2025-07-02 04:52:31.293 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.294 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.294 return
2025-07-02 04:52:31.294 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.294 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.294 else:
2025-07-02 04:52:31.294 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.294 eqi = None
2025-07-02 04:52:31.294
2025-07-02 04:52:31.294 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.294 # identical
2025-07-02 04:52:31.294
2025-07-02 04:52:31.294 # pump out diffs from before the synch point
2025-07-02 04:52:31.294 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.294
2025-07-02 04:52:31.294 # do intraline marking on the synch pair
2025-07-02 04:52:31.294 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.294 if eqi is None:
2025-07-02 04:52:31.294 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.294 atags = btags = ""
2025-07-02 04:52:31.294 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.294 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.295 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.295 if tag == 'replace':
2025-07-02 04:52:31.295 atags += '^' * la
2025-07-02 04:52:31.295 btags += '^' * lb
2025-07-02 04:52:31.295 elif tag == 'delete':
2025-07-02 04:52:31.295 atags += '-' * la
2025-07-02 04:52:31.295 elif tag == 'insert':
2025-07-02 04:52:31.295 btags += '+' * lb
2025-07-02 04:52:31.295 elif tag == 'equal':
2025-07-02 04:52:31.295 atags += ' ' * la
2025-07-02 04:52:31.295 btags += ' ' * lb
2025-07-02 04:52:31.295 else:
2025-07-02 04:52:31.295 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.295 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.295 else:
2025-07-02 04:52:31.295 # the synch pair is identical
2025-07-02 04:52:31.295 yield ' ' + aelt
2025-07-02 04:52:31.295
2025-07-02 04:52:31.295 # pump out diffs from after the synch point
2025-07-02 04:52:31.296 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.296
2025-07-02 04:52:31.296 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.296 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.296
2025-07-02 04:52:31.296 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.296 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.296 alo = 18, ahi = 1101
2025-07-02 04:52:31.296 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.296 blo = 18, bhi = 1101
2025-07-02 04:52:31.296
2025-07-02 04:52:31.296 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.296 g = []
2025-07-02 04:52:31.296 if alo < ahi:
2025-07-02 04:52:31.296 if blo < bhi:
2025-07-02 04:52:31.296 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.296 else:
2025-07-02 04:52:31.296 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.296 elif blo < bhi:
2025-07-02 04:52:31.296 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.297
2025-07-02 04:52:31.297 > yield from g
2025-07-02 04:52:31.297
2025-07-02 04:52:31.297 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.297 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.297
2025-07-02 04:52:31.297 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.297 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.297 alo = 18, ahi = 1101
2025-07-02 04:52:31.297 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.297 blo = 18, bhi = 1101
2025-07-02 04:52:31.297
2025-07-02 04:52:31.297 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.297 r"""
2025-07-02 04:52:31.297 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.297 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.297 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.297 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.297
2025-07-02 04:52:31.297 Example:
2025-07-02 04:52:31.297
2025-07-02 04:52:31.298 >>> d = Differ()
2025-07-02 04:52:31.298 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.298 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.298 >>> print(''.join(results), end="")
2025-07-02 04:52:31.298 - abcDefghiJkl
2025-07-02 04:52:31.298 + abcdefGhijkl
2025-07-02 04:52:31.298 """
2025-07-02 04:52:31.298
2025-07-02 04:52:31.298 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.298 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.298 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.298 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.298 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.298
2025-07-02 04:52:31.298 # search for the pair that matches best without being identical
2025-07-02 04:52:31.298 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.298 # on junk -- unless we have to)
2025-07-02 04:52:31.299 for j in range(blo, bhi):
2025-07-02 04:52:31.299 bj = b[j]
2025-07-02 04:52:31.299 cruncher.set_seq2(bj)
2025-07-02 04:52:31.299 for i in range(alo, ahi):
2025-07-02 04:52:31.299 ai = a[i]
2025-07-02 04:52:31.299 if ai == bj:
2025-07-02 04:52:31.299 if eqi is None:
2025-07-02 04:52:31.299 eqi, eqj = i, j
2025-07-02 04:52:31.299 continue
2025-07-02 04:52:31.299 cruncher.set_seq1(ai)
2025-07-02 04:52:31.299 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.299 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.299 # compares by a factor of 3.
2025-07-02 04:52:31.299 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.299 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.299 # of the computation is cached by cruncher
2025-07-02 04:52:31.299 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.299 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.299 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.299 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.299 if best_ratio < cutoff:
2025-07-02 04:52:31.300 # no non-identical "pretty close" pair
2025-07-02 04:52:31.300 if eqi is None:
2025-07-02 04:52:31.300 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.300 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.300 return
2025-07-02 04:52:31.300 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.300 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.300 else:
2025-07-02 04:52:31.300 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.300 eqi = None
2025-07-02 04:52:31.300
2025-07-02 04:52:31.300 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.300 # identical
2025-07-02 04:52:31.300
2025-07-02 04:52:31.300 # pump out diffs from before the synch point
2025-07-02 04:52:31.300 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.300
2025-07-02 04:52:31.300 # do intraline marking on the synch pair
2025-07-02 04:52:31.300 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.300 if eqi is None:
2025-07-02 04:52:31.301 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.301 atags = btags = ""
2025-07-02 04:52:31.301 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.301 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.301 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.301 if tag == 'replace':
2025-07-02 04:52:31.301 atags += '^' * la
2025-07-02 04:52:31.301 btags += '^' * lb
2025-07-02 04:52:31.301 elif tag == 'delete':
2025-07-02 04:52:31.301 atags += '-' * la
2025-07-02 04:52:31.301 elif tag == 'insert':
2025-07-02 04:52:31.301 btags += '+' * lb
2025-07-02 04:52:31.301 elif tag == 'equal':
2025-07-02 04:52:31.301 atags += ' ' * la
2025-07-02 04:52:31.301 btags += ' ' * lb
2025-07-02 04:52:31.301 else:
2025-07-02 04:52:31.301 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.301 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.301 else:
2025-07-02 04:52:31.301 # the synch pair is identical
2025-07-02 04:52:31.301 yield ' ' + aelt
2025-07-02 04:52:31.302
2025-07-02 04:52:31.302 # pump out diffs from after the synch point
2025-07-02 04:52:31.302 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.302
2025-07-02 04:52:31.302 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.302 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.302
2025-07-02 04:52:31.302 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.302 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.302 alo = 19, ahi = 1101
2025-07-02 04:52:31.302 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.302 blo = 19, bhi = 1101
2025-07-02 04:52:31.302
2025-07-02 04:52:31.302 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.302 g = []
2025-07-02 04:52:31.302 if alo < ahi:
2025-07-02 04:52:31.302 if blo < bhi:
2025-07-02 04:52:31.302 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.302 else:
2025-07-02 04:52:31.302 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.303 elif blo < bhi:
2025-07-02 04:52:31.303 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.303
2025-07-02 04:52:31.303 > yield from g
2025-07-02 04:52:31.303
2025-07-02 04:52:31.303 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.303 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.303
2025-07-02 04:52:31.303 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.303 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.303 alo = 19, ahi = 1101
2025-07-02 04:52:31.303 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.303 blo = 19, bhi = 1101
2025-07-02 04:52:31.303
2025-07-02 04:52:31.303 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.303 r"""
2025-07-02 04:52:31.303 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.303 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.303 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.304 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.304
2025-07-02 04:52:31.304 Example:
2025-07-02 04:52:31.304
2025-07-02 04:52:31.304 >>> d = Differ()
2025-07-02 04:52:31.304 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.304 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.304 >>> print(''.join(results), end="")
2025-07-02 04:52:31.304 - abcDefghiJkl
2025-07-02 04:52:31.304 + abcdefGhijkl
2025-07-02 04:52:31.304 """
2025-07-02 04:52:31.304
2025-07-02 04:52:31.304 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.304 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.304 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.304 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.304 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.304
2025-07-02 04:52:31.305 # search for the pair that matches best without being identical
2025-07-02 04:52:31.305 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.305 # on junk -- unless we have to)
2025-07-02 04:52:31.305 for j in range(blo, bhi):
2025-07-02 04:52:31.305 bj = b[j]
2025-07-02 04:52:31.305 cruncher.set_seq2(bj)
2025-07-02 04:52:31.305 for i in range(alo, ahi):
2025-07-02 04:52:31.305 ai = a[i]
2025-07-02 04:52:31.305 if ai == bj:
2025-07-02 04:52:31.305 if eqi is None:
2025-07-02 04:52:31.305 eqi, eqj = i, j
2025-07-02 04:52:31.305 continue
2025-07-02 04:52:31.305 cruncher.set_seq1(ai)
2025-07-02 04:52:31.305 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.305 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.305 # compares by a factor of 3.
2025-07-02 04:52:31.305 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.305 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.305 # of the computation is cached by cruncher
2025-07-02 04:52:31.305 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.305 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.306 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.306 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.306 if best_ratio < cutoff:
2025-07-02 04:52:31.306 # no non-identical "pretty close" pair
2025-07-02 04:52:31.306 if eqi is None:
2025-07-02 04:52:31.306 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.306 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.306 return
2025-07-02 04:52:31.306 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.306 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.306 else:
2025-07-02 04:52:31.306 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.306 eqi = None
2025-07-02 04:52:31.306
2025-07-02 04:52:31.306 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.306 # identical
2025-07-02 04:52:31.306
2025-07-02 04:52:31.306 # pump out diffs from before the synch point
2025-07-02 04:52:31.306 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.306
2025-07-02 04:52:31.306 # do intraline marking on the synch pair
2025-07-02 04:52:31.307 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.307 if eqi is None:
2025-07-02 04:52:31.307 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.307 atags = btags = ""
2025-07-02 04:52:31.307 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.307 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.307 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.307 if tag == 'replace':
2025-07-02 04:52:31.307 atags += '^' * la
2025-07-02 04:52:31.307 btags += '^' * lb
2025-07-02 04:52:31.307 elif tag == 'delete':
2025-07-02 04:52:31.307 atags += '-' * la
2025-07-02 04:52:31.307 elif tag == 'insert':
2025-07-02 04:52:31.307 btags += '+' * lb
2025-07-02 04:52:31.307 elif tag == 'equal':
2025-07-02 04:52:31.307 atags += ' ' * la
2025-07-02 04:52:31.307 btags += ' ' * lb
2025-07-02 04:52:31.307 else:
2025-07-02 04:52:31.307 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.307 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.308 else:
2025-07-02 04:52:31.308 # the synch pair is identical
2025-07-02 04:52:31.308 yield ' ' + aelt
2025-07-02 04:52:31.308
2025-07-02 04:52:31.308 # pump out diffs from after the synch point
2025-07-02 04:52:31.308 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.308
2025-07-02 04:52:31.308 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.308 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.308
2025-07-02 04:52:31.308 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.308 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.308 alo = 20, ahi = 1101
2025-07-02 04:52:31.308 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.308 blo = 20, bhi = 1101
2025-07-02 04:52:31.308
2025-07-02 04:52:31.308 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.308 g = []
2025-07-02 04:52:31.308 if alo < ahi:
2025-07-02 04:52:31.308 if blo < bhi:
2025-07-02 04:52:31.308 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.309 else:
2025-07-02 04:52:31.309 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.309 elif blo < bhi:
2025-07-02 04:52:31.309 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.309
2025-07-02 04:52:31.309 > yield from g
2025-07-02 04:52:31.309
2025-07-02 04:52:31.309 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.309 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.309
2025-07-02 04:52:31.309 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.309 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.309 alo = 20, ahi = 1101
2025-07-02 04:52:31.309 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.309 blo = 20, bhi = 1101
2025-07-02 04:52:31.309
2025-07-02 04:52:31.309 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.309 r"""
2025-07-02 04:52:31.309 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.309 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.310 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.310 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.310
2025-07-02 04:52:31.310 Example:
2025-07-02 04:52:31.310
2025-07-02 04:52:31.310 >>> d = Differ()
2025-07-02 04:52:31.310 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.310 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.310 >>> print(''.join(results), end="")
2025-07-02 04:52:31.310 - abcDefghiJkl
2025-07-02 04:52:31.310 + abcdefGhijkl
2025-07-02 04:52:31.310 """
2025-07-02 04:52:31.310
2025-07-02 04:52:31.310 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.310 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.310 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.310 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.310 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.310
2025-07-02 04:52:31.311 # search for the pair that matches best without being identical
2025-07-02 04:52:31.311 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.311 # on junk -- unless we have to)
2025-07-02 04:52:31.311 for j in range(blo, bhi):
2025-07-02 04:52:31.311 bj = b[j]
2025-07-02 04:52:31.311 cruncher.set_seq2(bj)
2025-07-02 04:52:31.311 for i in range(alo, ahi):
2025-07-02 04:52:31.311 ai = a[i]
2025-07-02 04:52:31.311 if ai == bj:
2025-07-02 04:52:31.311 if eqi is None:
2025-07-02 04:52:31.311 eqi, eqj = i, j
2025-07-02 04:52:31.311 continue
2025-07-02 04:52:31.311 cruncher.set_seq1(ai)
2025-07-02 04:52:31.311 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.311 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.311 # compares by a factor of 3.
2025-07-02 04:52:31.311 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.311 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.311 # of the computation is cached by cruncher
2025-07-02 04:52:31.311 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.312 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.312 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.312 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.312 if best_ratio < cutoff:
2025-07-02 04:52:31.312 # no non-identical "pretty close" pair
2025-07-02 04:52:31.312 if eqi is None:
2025-07-02 04:52:31.312 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.312 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.312 return
2025-07-02 04:52:31.312 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.312 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.312 else:
2025-07-02 04:52:31.312 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.312 eqi = None
2025-07-02 04:52:31.312
2025-07-02 04:52:31.312 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.312 # identical
2025-07-02 04:52:31.312
2025-07-02 04:52:31.312 # pump out diffs from before the synch point
2025-07-02 04:52:31.313 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.313
2025-07-02 04:52:31.313 # do intraline marking on the synch pair
2025-07-02 04:52:31.313 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.313 if eqi is None:
2025-07-02 04:52:31.313 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.313 atags = btags = ""
2025-07-02 04:52:31.313 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.313 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.313 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.313 if tag == 'replace':
2025-07-02 04:52:31.313 atags += '^' * la
2025-07-02 04:52:31.313 btags += '^' * lb
2025-07-02 04:52:31.313 elif tag == 'delete':
2025-07-02 04:52:31.313 atags += '-' * la
2025-07-02 04:52:31.313 elif tag == 'insert':
2025-07-02 04:52:31.313 btags += '+' * lb
2025-07-02 04:52:31.313 elif tag == 'equal':
2025-07-02 04:52:31.313 atags += ' ' * la
2025-07-02 04:52:31.313 btags += ' ' * lb
2025-07-02 04:52:31.314 else:
2025-07-02 04:52:31.314 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.314 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.314 else:
2025-07-02 04:52:31.314 # the synch pair is identical
2025-07-02 04:52:31.314 yield ' ' + aelt
2025-07-02 04:52:31.314
2025-07-02 04:52:31.314 # pump out diffs from after the synch point
2025-07-02 04:52:31.314 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.314
2025-07-02 04:52:31.314 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.314 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.314
2025-07-02 04:52:31.314 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.314 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.314 alo = 21, ahi = 1101
2025-07-02 04:52:31.314 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.314 blo = 21, bhi = 1101
2025-07-02 04:52:31.314
2025-07-02 04:52:31.314 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.315 g = []
2025-07-02 04:52:31.315 if alo < ahi:
2025-07-02 04:52:31.315 if blo < bhi:
2025-07-02 04:52:31.315 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.315 else:
2025-07-02 04:52:31.315 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.315 elif blo < bhi:
2025-07-02 04:52:31.315 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.315
2025-07-02 04:52:31.315 > yield from g
2025-07-02 04:52:31.315
2025-07-02 04:52:31.315 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.315 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.315
2025-07-02 04:52:31.315 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.315 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.315 alo = 21, ahi = 1101
2025-07-02 04:52:31.315 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.315 blo = 21, bhi = 1101
2025-07-02 04:52:31.315
2025-07-02 04:52:31.315 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.316 r"""
2025-07-02 04:52:31.316 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.316 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.316 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.316 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.316
2025-07-02 04:52:31.316 Example:
2025-07-02 04:52:31.316
2025-07-02 04:52:31.316 >>> d = Differ()
2025-07-02 04:52:31.316 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.316 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.316 >>> print(''.join(results), end="")
2025-07-02 04:52:31.316 - abcDefghiJkl
2025-07-02 04:52:31.316 + abcdefGhijkl
2025-07-02 04:52:31.316 """
2025-07-02 04:52:31.316
2025-07-02 04:52:31.316 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.316 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.317 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.317 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.317 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.317
2025-07-02 04:52:31.317 # search for the pair that matches best without being identical
2025-07-02 04:52:31.317 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.317 # on junk -- unless we have to)
2025-07-02 04:52:31.317 for j in range(blo, bhi):
2025-07-02 04:52:31.317 bj = b[j]
2025-07-02 04:52:31.317 cruncher.set_seq2(bj)
2025-07-02 04:52:31.317 for i in range(alo, ahi):
2025-07-02 04:52:31.317 ai = a[i]
2025-07-02 04:52:31.317 if ai == bj:
2025-07-02 04:52:31.317 if eqi is None:
2025-07-02 04:52:31.317 eqi, eqj = i, j
2025-07-02 04:52:31.317 continue
2025-07-02 04:52:31.317 cruncher.set_seq1(ai)
2025-07-02 04:52:31.317 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.317 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.317 # compares by a factor of 3.
2025-07-02 04:52:31.317 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.318 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.318 # of the computation is cached by cruncher
2025-07-02 04:52:31.318 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.318 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.318 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.318 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.318 if best_ratio < cutoff:
2025-07-02 04:52:31.318 # no non-identical "pretty close" pair
2025-07-02 04:52:31.318 if eqi is None:
2025-07-02 04:52:31.318 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.318 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.318 return
2025-07-02 04:52:31.318 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.318 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.318 else:
2025-07-02 04:52:31.318 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.318 eqi = None
2025-07-02 04:52:31.318
2025-07-02 04:52:31.318 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.318 # identical
2025-07-02 04:52:31.319
2025-07-02 04:52:31.319 # pump out diffs from before the synch point
2025-07-02 04:52:31.319 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.319
2025-07-02 04:52:31.319 # do intraline marking on the synch pair
2025-07-02 04:52:31.319 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.319 if eqi is None:
2025-07-02 04:52:31.319 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.319 atags = btags = ""
2025-07-02 04:52:31.319 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.319 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.319 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.319 if tag == 'replace':
2025-07-02 04:52:31.319 atags += '^' * la
2025-07-02 04:52:31.319 btags += '^' * lb
2025-07-02 04:52:31.319 elif tag == 'delete':
2025-07-02 04:52:31.319 atags += '-' * la
2025-07-02 04:52:31.319 elif tag == 'insert':
2025-07-02 04:52:31.319 btags += '+' * lb
2025-07-02 04:52:31.319 elif tag == 'equal':
2025-07-02 04:52:31.319 atags += ' ' * la
2025-07-02 04:52:31.320 btags += ' ' * lb
2025-07-02 04:52:31.320 else:
2025-07-02 04:52:31.320 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.320 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.320 else:
2025-07-02 04:52:31.320 # the synch pair is identical
2025-07-02 04:52:31.320 yield ' ' + aelt
2025-07-02 04:52:31.320
2025-07-02 04:52:31.320 # pump out diffs from after the synch point
2025-07-02 04:52:31.320 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.320
2025-07-02 04:52:31.320 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.320 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.320
2025-07-02 04:52:31.320 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.320 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.320 alo = 22, ahi = 1101
2025-07-02 04:52:31.320 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.320 blo = 22, bhi = 1101
2025-07-02 04:52:31.320
2025-07-02 04:52:31.321 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.321 g = []
2025-07-02 04:52:31.321 if alo < ahi:
2025-07-02 04:52:31.321 if blo < bhi:
2025-07-02 04:52:31.321 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.321 else:
2025-07-02 04:52:31.321 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.321 elif blo < bhi:
2025-07-02 04:52:31.321 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.321
2025-07-02 04:52:31.321 > yield from g
2025-07-02 04:52:31.321
2025-07-02 04:52:31.321 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.321 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.321
2025-07-02 04:52:31.321 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.321 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.321 alo = 22, ahi = 1101
2025-07-02 04:52:31.321 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.321 blo = 22, bhi = 1101
2025-07-02 04:52:31.322
2025-07-02 04:52:31.322 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.322 r"""
2025-07-02 04:52:31.322 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.322 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.322 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.322 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.322
2025-07-02 04:52:31.322 Example:
2025-07-02 04:52:31.322
2025-07-02 04:52:31.322 >>> d = Differ()
2025-07-02 04:52:31.322 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.322 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.322 >>> print(''.join(results), end="")
2025-07-02 04:52:31.322 - abcDefghiJkl
2025-07-02 04:52:31.322 + abcdefGhijkl
2025-07-02 04:52:31.322 """
2025-07-02 04:52:31.322
2025-07-02 04:52:31.323 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.323 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.323 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.323 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.323 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.323
2025-07-02 04:52:31.323 # search for the pair that matches best without being identical
2025-07-02 04:52:31.323 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.323 # on junk -- unless we have to)
2025-07-02 04:52:31.323 for j in range(blo, bhi):
2025-07-02 04:52:31.323 bj = b[j]
2025-07-02 04:52:31.323 cruncher.set_seq2(bj)
2025-07-02 04:52:31.323 for i in range(alo, ahi):
2025-07-02 04:52:31.323 ai = a[i]
2025-07-02 04:52:31.323 if ai == bj:
2025-07-02 04:52:31.323 if eqi is None:
2025-07-02 04:52:31.323 eqi, eqj = i, j
2025-07-02 04:52:31.323 continue
2025-07-02 04:52:31.323 cruncher.set_seq1(ai)
2025-07-02 04:52:31.323 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.323 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.324 # compares by a factor of 3.
2025-07-02 04:52:31.324 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.324 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.324 # of the computation is cached by cruncher
2025-07-02 04:52:31.324 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.324 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.324 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.324 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.324 if best_ratio < cutoff:
2025-07-02 04:52:31.324 # no non-identical "pretty close" pair
2025-07-02 04:52:31.324 if eqi is None:
2025-07-02 04:52:31.324 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.324 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.324 return
2025-07-02 04:52:31.324 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.324 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.324 else:
2025-07-02 04:52:31.324 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.324 eqi = None
2025-07-02 04:52:31.324
2025-07-02 04:52:31.324 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.325 # identical
2025-07-02 04:52:31.325
2025-07-02 04:52:31.325 # pump out diffs from before the synch point
2025-07-02 04:52:31.325 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.325
2025-07-02 04:52:31.325 # do intraline marking on the synch pair
2025-07-02 04:52:31.325 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.325 if eqi is None:
2025-07-02 04:52:31.325 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.325 atags = btags = ""
2025-07-02 04:52:31.325 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.325 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.325 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.325 if tag == 'replace':
2025-07-02 04:52:31.325 atags += '^' * la
2025-07-02 04:52:31.325 btags += '^' * lb
2025-07-02 04:52:31.325 elif tag == 'delete':
2025-07-02 04:52:31.325 atags += '-' * la
2025-07-02 04:52:31.325 elif tag == 'insert':
2025-07-02 04:52:31.325 btags += '+' * lb
2025-07-02 04:52:31.326 elif tag == 'equal':
2025-07-02 04:52:31.326 atags += ' ' * la
2025-07-02 04:52:31.326 btags += ' ' * lb
2025-07-02 04:52:31.326 else:
2025-07-02 04:52:31.326 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.326 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.326 else:
2025-07-02 04:52:31.326 # the synch pair is identical
2025-07-02 04:52:31.326 yield ' ' + aelt
2025-07-02 04:52:31.326
2025-07-02 04:52:31.326 # pump out diffs from after the synch point
2025-07-02 04:52:31.326 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.326
2025-07-02 04:52:31.326 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.326 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.326
2025-07-02 04:52:31.326 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.326 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.326 alo = 23, ahi = 1101
2025-07-02 04:52:31.326 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.326 blo = 23, bhi = 1101
2025-07-02 04:52:31.327
2025-07-02 04:52:31.327 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.327 g = []
2025-07-02 04:52:31.327 if alo < ahi:
2025-07-02 04:52:31.327 if blo < bhi:
2025-07-02 04:52:31.327 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.327 else:
2025-07-02 04:52:31.327 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.327 elif blo < bhi:
2025-07-02 04:52:31.327 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.327
2025-07-02 04:52:31.327 > yield from g
2025-07-02 04:52:31.327
2025-07-02 04:52:31.327 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.327 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.327
2025-07-02 04:52:31.327 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.327 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.327 alo = 23, ahi = 1101
2025-07-02 04:52:31.327 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.328 blo = 23, bhi = 1101
2025-07-02 04:52:31.328
2025-07-02 04:52:31.328 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.328 r"""
2025-07-02 04:52:31.328 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.328 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.328 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.328 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.328
2025-07-02 04:52:31.328 Example:
2025-07-02 04:52:31.328
2025-07-02 04:52:31.328 >>> d = Differ()
2025-07-02 04:52:31.328 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.328 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.328 >>> print(''.join(results), end="")
2025-07-02 04:52:31.328 - abcDefghiJkl
2025-07-02 04:52:31.328 + abcdefGhijkl
2025-07-02 04:52:31.328 """
2025-07-02 04:52:31.328
2025-07-02 04:52:31.329 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.329 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.329 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.329 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.329 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.329
2025-07-02 04:52:31.329 # search for the pair that matches best without being identical
2025-07-02 04:52:31.329 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.329 # on junk -- unless we have to)
2025-07-02 04:52:31.329 for j in range(blo, bhi):
2025-07-02 04:52:31.329 bj = b[j]
2025-07-02 04:52:31.329 cruncher.set_seq2(bj)
2025-07-02 04:52:31.329 for i in range(alo, ahi):
2025-07-02 04:52:31.329 ai = a[i]
2025-07-02 04:52:31.329 if ai == bj:
2025-07-02 04:52:31.329 if eqi is None:
2025-07-02 04:52:31.329 eqi, eqj = i, j
2025-07-02 04:52:31.329 continue
2025-07-02 04:52:31.329 cruncher.set_seq1(ai)
2025-07-02 04:52:31.329 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.330 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.330 # compares by a factor of 3.
2025-07-02 04:52:31.330 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.330 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.330 # of the computation is cached by cruncher
2025-07-02 04:52:31.330 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.330 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.330 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.330 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.330 if best_ratio < cutoff:
2025-07-02 04:52:31.330 # no non-identical "pretty close" pair
2025-07-02 04:52:31.330 if eqi is None:
2025-07-02 04:52:31.330 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.330 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.330 return
2025-07-02 04:52:31.330 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.330 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.330 else:
2025-07-02 04:52:31.330 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.331 eqi = None
2025-07-02 04:52:31.331
2025-07-02 04:52:31.331 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.331 # identical
2025-07-02 04:52:31.331
2025-07-02 04:52:31.331 # pump out diffs from before the synch point
2025-07-02 04:52:31.331 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.331
2025-07-02 04:52:31.331 # do intraline marking on the synch pair
2025-07-02 04:52:31.331 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.331 if eqi is None:
2025-07-02 04:52:31.331 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.331 atags = btags = ""
2025-07-02 04:52:31.331 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.331 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.331 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.331 if tag == 'replace':
2025-07-02 04:52:31.331 atags += '^' * la
2025-07-02 04:52:31.331 btags += '^' * lb
2025-07-02 04:52:31.331 elif tag == 'delete':
2025-07-02 04:52:31.332 atags += '-' * la
2025-07-02 04:52:31.332 elif tag == 'insert':
2025-07-02 04:52:31.332 btags += '+' * lb
2025-07-02 04:52:31.332 elif tag == 'equal':
2025-07-02 04:52:31.332 atags += ' ' * la
2025-07-02 04:52:31.332 btags += ' ' * lb
2025-07-02 04:52:31.332 else:
2025-07-02 04:52:31.332 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.332 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.332 else:
2025-07-02 04:52:31.332 # the synch pair is identical
2025-07-02 04:52:31.332 yield ' ' + aelt
2025-07-02 04:52:31.332
2025-07-02 04:52:31.332 # pump out diffs from after the synch point
2025-07-02 04:52:31.332 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.332
2025-07-02 04:52:31.332 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.332 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.332
2025-07-02 04:52:31.332 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.333 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.333 alo = 26, ahi = 1101
2025-07-02 04:52:31.333 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.333 blo = 26, bhi = 1101
2025-07-02 04:52:31.333
2025-07-02 04:52:31.333 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.333 g = []
2025-07-02 04:52:31.333 if alo < ahi:
2025-07-02 04:52:31.333 if blo < bhi:
2025-07-02 04:52:31.333 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.333 else:
2025-07-02 04:52:31.333 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.333 elif blo < bhi:
2025-07-02 04:52:31.333 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.333
2025-07-02 04:52:31.333 > yield from g
2025-07-02 04:52:31.333
2025-07-02 04:52:31.333 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.333 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.333
2025-07-02 04:52:31.334 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.334 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.334 alo = 26, ahi = 1101
2025-07-02 04:52:31.334 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.334 blo = 26, bhi = 1101
2025-07-02 04:52:31.334
2025-07-02 04:52:31.334 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.334 r"""
2025-07-02 04:52:31.334 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.334 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.334 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.334 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.334
2025-07-02 04:52:31.334 Example:
2025-07-02 04:52:31.334
2025-07-02 04:52:31.334 >>> d = Differ()
2025-07-02 04:52:31.334 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.334 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.334 >>> print(''.join(results), end="")
2025-07-02 04:52:31.334 - abcDefghiJkl
2025-07-02 04:52:31.335 + abcdefGhijkl
2025-07-02 04:52:31.335 """
2025-07-02 04:52:31.335
2025-07-02 04:52:31.335 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.335 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.335 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.335 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.335 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.335
2025-07-02 04:52:31.335 # search for the pair that matches best without being identical
2025-07-02 04:52:31.335 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.335 # on junk -- unless we have to)
2025-07-02 04:52:31.335 for j in range(blo, bhi):
2025-07-02 04:52:31.335 bj = b[j]
2025-07-02 04:52:31.335 cruncher.set_seq2(bj)
2025-07-02 04:52:31.335 for i in range(alo, ahi):
2025-07-02 04:52:31.335 ai = a[i]
2025-07-02 04:52:31.335 if ai == bj:
2025-07-02 04:52:31.336 if eqi is None:
2025-07-02 04:52:31.336 eqi, eqj = i, j
2025-07-02 04:52:31.336 continue
2025-07-02 04:52:31.336 cruncher.set_seq1(ai)
2025-07-02 04:52:31.336 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.336 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.336 # compares by a factor of 3.
2025-07-02 04:52:31.336 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.336 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.336 # of the computation is cached by cruncher
2025-07-02 04:52:31.336 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.336 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.336 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.336 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.336 if best_ratio < cutoff:
2025-07-02 04:52:31.336 # no non-identical "pretty close" pair
2025-07-02 04:52:31.336 if eqi is None:
2025-07-02 04:52:31.336 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.336 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.337 return
2025-07-02 04:52:31.337 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.337 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.337 else:
2025-07-02 04:52:31.337 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.337 eqi = None
2025-07-02 04:52:31.337
2025-07-02 04:52:31.337 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.337 # identical
2025-07-02 04:52:31.337
2025-07-02 04:52:31.337 # pump out diffs from before the synch point
2025-07-02 04:52:31.337 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.337
2025-07-02 04:52:31.337 # do intraline marking on the synch pair
2025-07-02 04:52:31.337 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.337 if eqi is None:
2025-07-02 04:52:31.337 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.337 atags = btags = ""
2025-07-02 04:52:31.337 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.337 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.338 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.338 if tag == 'replace':
2025-07-02 04:52:31.338 atags += '^' * la
2025-07-02 04:52:31.338 btags += '^' * lb
2025-07-02 04:52:31.338 elif tag == 'delete':
2025-07-02 04:52:31.338 atags += '-' * la
2025-07-02 04:52:31.338 elif tag == 'insert':
2025-07-02 04:52:31.338 btags += '+' * lb
2025-07-02 04:52:31.338 elif tag == 'equal':
2025-07-02 04:52:31.338 atags += ' ' * la
2025-07-02 04:52:31.338 btags += ' ' * lb
2025-07-02 04:52:31.338 else:
2025-07-02 04:52:31.338 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.338 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.338 else:
2025-07-02 04:52:31.338 # the synch pair is identical
2025-07-02 04:52:31.338 yield ' ' + aelt
2025-07-02 04:52:31.338
2025-07-02 04:52:31.338 # pump out diffs from after the synch point
2025-07-02 04:52:31.338 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.339
2025-07-02 04:52:31.339 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.339 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.339
2025-07-02 04:52:31.339 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.339 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.339 alo = 27, ahi = 1101
2025-07-02 04:52:31.339 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.339 blo = 27, bhi = 1101
2025-07-02 04:52:31.339
2025-07-02 04:52:31.339 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.339 g = []
2025-07-02 04:52:31.339 if alo < ahi:
2025-07-02 04:52:31.339 if blo < bhi:
2025-07-02 04:52:31.339 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.339 else:
2025-07-02 04:52:31.339 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.339 elif blo < bhi:
2025-07-02 04:52:31.339 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.340
2025-07-02 04:52:31.340 > yield from g
2025-07-02 04:52:31.340
2025-07-02 04:52:31.340 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.340 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.340
2025-07-02 04:52:31.340 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.340 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.340 alo = 27, ahi = 1101
2025-07-02 04:52:31.340 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.340 blo = 27, bhi = 1101
2025-07-02 04:52:31.340
2025-07-02 04:52:31.340 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.340 r"""
2025-07-02 04:52:31.340 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.340 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.340 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.340 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.340
2025-07-02 04:52:31.340 Example:
2025-07-02 04:52:31.341
2025-07-02 04:52:31.341 >>> d = Differ()
2025-07-02 04:52:31.341 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.341 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.341 >>> print(''.join(results), end="")
2025-07-02 04:52:31.341 - abcDefghiJkl
2025-07-02 04:52:31.341 + abcdefGhijkl
2025-07-02 04:52:31.341 """
2025-07-02 04:52:31.341
2025-07-02 04:52:31.341 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.341 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.341 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.341 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.341 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.341
2025-07-02 04:52:31.341 # search for the pair that matches best without being identical
2025-07-02 04:52:31.341 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.341 # on junk -- unless we have to)
2025-07-02 04:52:31.342 for j in range(blo, bhi):
2025-07-02 04:52:31.342 bj = b[j]
2025-07-02 04:52:31.342 cruncher.set_seq2(bj)
2025-07-02 04:52:31.342 for i in range(alo, ahi):
2025-07-02 04:52:31.342 ai = a[i]
2025-07-02 04:52:31.342 if ai == bj:
2025-07-02 04:52:31.342 if eqi is None:
2025-07-02 04:52:31.342 eqi, eqj = i, j
2025-07-02 04:52:31.342 continue
2025-07-02 04:52:31.342 cruncher.set_seq1(ai)
2025-07-02 04:52:31.342 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.342 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.342 # compares by a factor of 3.
2025-07-02 04:52:31.342 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.342 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.342 # of the computation is cached by cruncher
2025-07-02 04:52:31.342 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.342 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.342 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.342 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.343 if best_ratio < cutoff:
2025-07-02 04:52:31.343 # no non-identical "pretty close" pair
2025-07-02 04:52:31.343 if eqi is None:
2025-07-02 04:52:31.343 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.343 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.343 return
2025-07-02 04:52:31.343 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.343 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.343 else:
2025-07-02 04:52:31.343 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.343 eqi = None
2025-07-02 04:52:31.343
2025-07-02 04:52:31.343 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.343 # identical
2025-07-02 04:52:31.343
2025-07-02 04:52:31.343 # pump out diffs from before the synch point
2025-07-02 04:52:31.343 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.343
2025-07-02 04:52:31.343 # do intraline marking on the synch pair
2025-07-02 04:52:31.343 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.344 if eqi is None:
2025-07-02 04:52:31.344 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.344 atags = btags = ""
2025-07-02 04:52:31.344 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.344 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.344 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.344 if tag == 'replace':
2025-07-02 04:52:31.344 atags += '^' * la
2025-07-02 04:52:31.344 btags += '^' * lb
2025-07-02 04:52:31.344 elif tag == 'delete':
2025-07-02 04:52:31.344 atags += '-' * la
2025-07-02 04:52:31.344 elif tag == 'insert':
2025-07-02 04:52:31.344 btags += '+' * lb
2025-07-02 04:52:31.344 elif tag == 'equal':
2025-07-02 04:52:31.344 atags += ' ' * la
2025-07-02 04:52:31.344 btags += ' ' * lb
2025-07-02 04:52:31.344 else:
2025-07-02 04:52:31.344 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.344 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.345 else:
2025-07-02 04:52:31.345 # the synch pair is identical
2025-07-02 04:52:31.345 yield ' ' + aelt
2025-07-02 04:52:31.345
2025-07-02 04:52:31.345 # pump out diffs from after the synch point
2025-07-02 04:52:31.345 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.345
2025-07-02 04:52:31.345 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.345 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.345
2025-07-02 04:52:31.345 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.345 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.345 alo = 28, ahi = 1101
2025-07-02 04:52:31.345 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.345 blo = 28, bhi = 1101
2025-07-02 04:52:31.345
2025-07-02 04:52:31.345 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.345 g = []
2025-07-02 04:52:31.345 if alo < ahi:
2025-07-02 04:52:31.345 if blo < bhi:
2025-07-02 04:52:31.346 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.346 else:
2025-07-02 04:52:31.346 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.346 elif blo < bhi:
2025-07-02 04:52:31.346 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.346
2025-07-02 04:52:31.346 > yield from g
2025-07-02 04:52:31.346
2025-07-02 04:52:31.346 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.346 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.346
2025-07-02 04:52:31.346 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.346 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.346 alo = 28, ahi = 1101
2025-07-02 04:52:31.346 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.346 blo = 28, bhi = 1101
2025-07-02 04:52:31.346
2025-07-02 04:52:31.346 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.347 r"""
2025-07-02 04:52:31.347 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.347 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.347 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.347 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.347
2025-07-02 04:52:31.347 Example:
2025-07-02 04:52:31.347
2025-07-02 04:52:31.347 >>> d = Differ()
2025-07-02 04:52:31.347 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.347 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.347 >>> print(''.join(results), end="")
2025-07-02 04:52:31.347 - abcDefghiJkl
2025-07-02 04:52:31.347 + abcdefGhijkl
2025-07-02 04:52:31.347 """
2025-07-02 04:52:31.347
2025-07-02 04:52:31.347 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.347 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.348 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.348 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.348 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.348
2025-07-02 04:52:31.348 # search for the pair that matches best without being identical
2025-07-02 04:52:31.348 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.348 # on junk -- unless we have to)
2025-07-02 04:52:31.348 for j in range(blo, bhi):
2025-07-02 04:52:31.348 bj = b[j]
2025-07-02 04:52:31.348 cruncher.set_seq2(bj)
2025-07-02 04:52:31.348 for i in range(alo, ahi):
2025-07-02 04:52:31.348 ai = a[i]
2025-07-02 04:52:31.348 if ai == bj:
2025-07-02 04:52:31.348 if eqi is None:
2025-07-02 04:52:31.348 eqi, eqj = i, j
2025-07-02 04:52:31.348 continue
2025-07-02 04:52:31.348 cruncher.set_seq1(ai)
2025-07-02 04:52:31.348 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.348 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.348 # compares by a factor of 3.
2025-07-02 04:52:31.349 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.349 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.349 # of the computation is cached by cruncher
2025-07-02 04:52:31.349 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.349 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.349 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.349 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.349 if best_ratio < cutoff:
2025-07-02 04:52:31.349 # no non-identical "pretty close" pair
2025-07-02 04:52:31.349 if eqi is None:
2025-07-02 04:52:31.349 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.349 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.349 return
2025-07-02 04:52:31.349 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.349 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.349 else:
2025-07-02 04:52:31.349 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.349 eqi = None
2025-07-02 04:52:31.349
2025-07-02 04:52:31.349 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.350 # identical
2025-07-02 04:52:31.350
2025-07-02 04:52:31.350 # pump out diffs from before the synch point
2025-07-02 04:52:31.350 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.350
2025-07-02 04:52:31.350 # do intraline marking on the synch pair
2025-07-02 04:52:31.350 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.350 if eqi is None:
2025-07-02 04:52:31.350 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.350 atags = btags = ""
2025-07-02 04:52:31.350 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.350 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.350 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.350 if tag == 'replace':
2025-07-02 04:52:31.350 atags += '^' * la
2025-07-02 04:52:31.350 btags += '^' * lb
2025-07-02 04:52:31.350 elif tag == 'delete':
2025-07-02 04:52:31.350 atags += '-' * la
2025-07-02 04:52:31.350 elif tag == 'insert':
2025-07-02 04:52:31.350 btags += '+' * lb
2025-07-02 04:52:31.351 elif tag == 'equal':
2025-07-02 04:52:31.351 atags += ' ' * la
2025-07-02 04:52:31.351 btags += ' ' * lb
2025-07-02 04:52:31.351 else:
2025-07-02 04:52:31.351 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.351 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.351 else:
2025-07-02 04:52:31.351 # the synch pair is identical
2025-07-02 04:52:31.351 yield ' ' + aelt
2025-07-02 04:52:31.351
2025-07-02 04:52:31.351 # pump out diffs from after the synch point
2025-07-02 04:52:31.351 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.351
2025-07-02 04:52:31.351 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.351 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.351
2025-07-02 04:52:31.351 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.351 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.351 alo = 29, ahi = 1101
2025-07-02 04:52:31.351 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.352 blo = 29, bhi = 1101
2025-07-02 04:52:31.352
2025-07-02 04:52:31.352 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.352 g = []
2025-07-02 04:52:31.352 if alo < ahi:
2025-07-02 04:52:31.352 if blo < bhi:
2025-07-02 04:52:31.352 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.352 else:
2025-07-02 04:52:31.352 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.352 elif blo < bhi:
2025-07-02 04:52:31.352 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.352
2025-07-02 04:52:31.352 > yield from g
2025-07-02 04:52:31.352
2025-07-02 04:52:31.352 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.352 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.352
2025-07-02 04:52:31.352 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.352 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.352 alo = 29, ahi = 1101
2025-07-02 04:52:31.353 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.353 blo = 29, bhi = 1101
2025-07-02 04:52:31.353
2025-07-02 04:52:31.353 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.353 r"""
2025-07-02 04:52:31.353 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.353 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.353 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.353 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.353
2025-07-02 04:52:31.353 Example:
2025-07-02 04:52:31.353
2025-07-02 04:52:31.353 >>> d = Differ()
2025-07-02 04:52:31.353 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.353 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.353 >>> print(''.join(results), end="")
2025-07-02 04:52:31.353 - abcDefghiJkl
2025-07-02 04:52:31.353 + abcdefGhijkl
2025-07-02 04:52:31.354 """
2025-07-02 04:52:31.354
2025-07-02 04:52:31.354 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.354 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.354 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.354 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.354 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.354
2025-07-02 04:52:31.354 # search for the pair that matches best without being identical
2025-07-02 04:52:31.354 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.354 # on junk -- unless we have to)
2025-07-02 04:52:31.354 for j in range(blo, bhi):
2025-07-02 04:52:31.354 bj = b[j]
2025-07-02 04:52:31.354 cruncher.set_seq2(bj)
2025-07-02 04:52:31.354 for i in range(alo, ahi):
2025-07-02 04:52:31.354 ai = a[i]
2025-07-02 04:52:31.354 if ai == bj:
2025-07-02 04:52:31.354 if eqi is None:
2025-07-02 04:52:31.354 eqi, eqj = i, j
2025-07-02 04:52:31.354 continue
2025-07-02 04:52:31.355 cruncher.set_seq1(ai)
2025-07-02 04:52:31.355 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.355 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.355 # compares by a factor of 3.
2025-07-02 04:52:31.355 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.355 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.355 # of the computation is cached by cruncher
2025-07-02 04:52:31.355 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.355 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.355 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.355 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.355 if best_ratio < cutoff:
2025-07-02 04:52:31.355 # no non-identical "pretty close" pair
2025-07-02 04:52:31.355 if eqi is None:
2025-07-02 04:52:31.355 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.355 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.355 return
2025-07-02 04:52:31.355 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.355 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.356 else:
2025-07-02 04:52:31.356 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.356 eqi = None
2025-07-02 04:52:31.356
2025-07-02 04:52:31.356 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.356 # identical
2025-07-02 04:52:31.356
2025-07-02 04:52:31.356 # pump out diffs from before the synch point
2025-07-02 04:52:31.356 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.356
2025-07-02 04:52:31.356 # do intraline marking on the synch pair
2025-07-02 04:52:31.356 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.356 if eqi is None:
2025-07-02 04:52:31.356 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.356 atags = btags = ""
2025-07-02 04:52:31.356 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.356 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.356 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.356 if tag == 'replace':
2025-07-02 04:52:31.356 atags += '^' * la
2025-07-02 04:52:31.357 btags += '^' * lb
2025-07-02 04:52:31.357 elif tag == 'delete':
2025-07-02 04:52:31.357 atags += '-' * la
2025-07-02 04:52:31.357 elif tag == 'insert':
2025-07-02 04:52:31.357 btags += '+' * lb
2025-07-02 04:52:31.357 elif tag == 'equal':
2025-07-02 04:52:31.357 atags += ' ' * la
2025-07-02 04:52:31.357 btags += ' ' * lb
2025-07-02 04:52:31.357 else:
2025-07-02 04:52:31.357 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.357 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.357 else:
2025-07-02 04:52:31.357 # the synch pair is identical
2025-07-02 04:52:31.357 yield ' ' + aelt
2025-07-02 04:52:31.357
2025-07-02 04:52:31.357 # pump out diffs from after the synch point
2025-07-02 04:52:31.357 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.357
2025-07-02 04:52:31.357 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.357 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.358
2025-07-02 04:52:31.358 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.358 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.358 alo = 30, ahi = 1101
2025-07-02 04:52:31.358 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.358 blo = 30, bhi = 1101
2025-07-02 04:52:31.358
2025-07-02 04:52:31.358 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.358 g = []
2025-07-02 04:52:31.358 if alo < ahi:
2025-07-02 04:52:31.358 if blo < bhi:
2025-07-02 04:52:31.358 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.358 else:
2025-07-02 04:52:31.358 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.358 elif blo < bhi:
2025-07-02 04:52:31.358 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.358
2025-07-02 04:52:31.358 > yield from g
2025-07-02 04:52:31.358
2025-07-02 04:52:31.358 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.358 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.359
2025-07-02 04:52:31.359 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.359 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.359 alo = 30, ahi = 1101
2025-07-02 04:52:31.359 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.359 blo = 30, bhi = 1101
2025-07-02 04:52:31.359
2025-07-02 04:52:31.359 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.359 r"""
2025-07-02 04:52:31.359 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.359 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.359 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.359 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.359
2025-07-02 04:52:31.359 Example:
2025-07-02 04:52:31.359
2025-07-02 04:52:31.359 >>> d = Differ()
2025-07-02 04:52:31.359 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.359 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.359 >>> print(''.join(results), end="")
2025-07-02 04:52:31.360 - abcDefghiJkl
2025-07-02 04:52:31.360 + abcdefGhijkl
2025-07-02 04:52:31.360 """
2025-07-02 04:52:31.360
2025-07-02 04:52:31.360 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.360 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.360 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.360 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.360 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.360
2025-07-02 04:52:31.360 # search for the pair that matches best without being identical
2025-07-02 04:52:31.360 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.360 # on junk -- unless we have to)
2025-07-02 04:52:31.360 for j in range(blo, bhi):
2025-07-02 04:52:31.360 bj = b[j]
2025-07-02 04:52:31.360 cruncher.set_seq2(bj)
2025-07-02 04:52:31.360 for i in range(alo, ahi):
2025-07-02 04:52:31.361 ai = a[i]
2025-07-02 04:52:31.361 if ai == bj:
2025-07-02 04:52:31.361 if eqi is None:
2025-07-02 04:52:31.361 eqi, eqj = i, j
2025-07-02 04:52:31.361 continue
2025-07-02 04:52:31.361 cruncher.set_seq1(ai)
2025-07-02 04:52:31.361 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.361 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.361 # compares by a factor of 3.
2025-07-02 04:52:31.361 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.361 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.361 # of the computation is cached by cruncher
2025-07-02 04:52:31.361 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.361 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.361 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.361 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.361 if best_ratio < cutoff:
2025-07-02 04:52:31.361 # no non-identical "pretty close" pair
2025-07-02 04:52:31.361 if eqi is None:
2025-07-02 04:52:31.361 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.361 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.362 return
2025-07-02 04:52:31.362 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.362 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.362 else:
2025-07-02 04:52:31.362 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.362 eqi = None
2025-07-02 04:52:31.362
2025-07-02 04:52:31.362 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.362 # identical
2025-07-02 04:52:31.362
2025-07-02 04:52:31.362 # pump out diffs from before the synch point
2025-07-02 04:52:31.362 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.362
2025-07-02 04:52:31.362 # do intraline marking on the synch pair
2025-07-02 04:52:31.362 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.362 if eqi is None:
2025-07-02 04:52:31.362 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.362 atags = btags = ""
2025-07-02 04:52:31.362 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.362 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.363 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.363 if tag == 'replace':
2025-07-02 04:52:31.363 atags += '^' * la
2025-07-02 04:52:31.363 btags += '^' * lb
2025-07-02 04:52:31.363 elif tag == 'delete':
2025-07-02 04:52:31.363 atags += '-' * la
2025-07-02 04:52:31.363 elif tag == 'insert':
2025-07-02 04:52:31.363 btags += '+' * lb
2025-07-02 04:52:31.363 elif tag == 'equal':
2025-07-02 04:52:31.363 atags += ' ' * la
2025-07-02 04:52:31.363 btags += ' ' * lb
2025-07-02 04:52:31.363 else:
2025-07-02 04:52:31.363 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.363 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.363 else:
2025-07-02 04:52:31.363 # the synch pair is identical
2025-07-02 04:52:31.363 yield ' ' + aelt
2025-07-02 04:52:31.363
2025-07-02 04:52:31.363 # pump out diffs from after the synch point
2025-07-02 04:52:31.363 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.364
2025-07-02 04:52:31.364 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.364 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.364
2025-07-02 04:52:31.364 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.364 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.364 alo = 31, ahi = 1101
2025-07-02 04:52:31.364 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.364 blo = 31, bhi = 1101
2025-07-02 04:52:31.364
2025-07-02 04:52:31.364 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.364 g = []
2025-07-02 04:52:31.364 if alo < ahi:
2025-07-02 04:52:31.364 if blo < bhi:
2025-07-02 04:52:31.364 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.364 else:
2025-07-02 04:52:31.364 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.364 elif blo < bhi:
2025-07-02 04:52:31.364 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.365
2025-07-02 04:52:31.365 > yield from g
2025-07-02 04:52:31.365
2025-07-02 04:52:31.365 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.365 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.365
2025-07-02 04:52:31.365 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.365 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.365 alo = 31, ahi = 1101
2025-07-02 04:52:31.365 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.365 blo = 31, bhi = 1101
2025-07-02 04:52:31.365
2025-07-02 04:52:31.365 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.365 r"""
2025-07-02 04:52:31.365 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.365 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.365 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.365 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.365
2025-07-02 04:52:31.365 Example:
2025-07-02 04:52:31.366
2025-07-02 04:52:31.366 >>> d = Differ()
2025-07-02 04:52:31.366 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.366 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.366 >>> print(''.join(results), end="")
2025-07-02 04:52:31.366 - abcDefghiJkl
2025-07-02 04:52:31.366 + abcdefGhijkl
2025-07-02 04:52:31.366 """
2025-07-02 04:52:31.366
2025-07-02 04:52:31.366 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.366 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.366 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.366 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.366 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.366
2025-07-02 04:52:31.366 # search for the pair that matches best without being identical
2025-07-02 04:52:31.366 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.366 # on junk -- unless we have to)
2025-07-02 04:52:31.367 for j in range(blo, bhi):
2025-07-02 04:52:31.367 bj = b[j]
2025-07-02 04:52:31.367 cruncher.set_seq2(bj)
2025-07-02 04:52:31.367 for i in range(alo, ahi):
2025-07-02 04:52:31.367 ai = a[i]
2025-07-02 04:52:31.367 if ai == bj:
2025-07-02 04:52:31.367 if eqi is None:
2025-07-02 04:52:31.367 eqi, eqj = i, j
2025-07-02 04:52:31.367 continue
2025-07-02 04:52:31.367 cruncher.set_seq1(ai)
2025-07-02 04:52:31.367 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.367 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.367 # compares by a factor of 3.
2025-07-02 04:52:31.367 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.367 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.367 # of the computation is cached by cruncher
2025-07-02 04:52:31.367 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.367 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.367 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.367 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.367 if best_ratio < cutoff:
2025-07-02 04:52:31.368 # no non-identical "pretty close" pair
2025-07-02 04:52:31.368 if eqi is None:
2025-07-02 04:52:31.368 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.368 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.368 return
2025-07-02 04:52:31.368 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.368 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.368 else:
2025-07-02 04:52:31.368 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.368 eqi = None
2025-07-02 04:52:31.368
2025-07-02 04:52:31.368 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.368 # identical
2025-07-02 04:52:31.368
2025-07-02 04:52:31.368 # pump out diffs from before the synch point
2025-07-02 04:52:31.368 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.368
2025-07-02 04:52:31.368 # do intraline marking on the synch pair
2025-07-02 04:52:31.368 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.368 if eqi is None:
2025-07-02 04:52:31.369 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.369 atags = btags = ""
2025-07-02 04:52:31.369 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.369 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.369 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.369 if tag == 'replace':
2025-07-02 04:52:31.369 atags += '^' * la
2025-07-02 04:52:31.369 btags += '^' * lb
2025-07-02 04:52:31.369 elif tag == 'delete':
2025-07-02 04:52:31.369 atags += '-' * la
2025-07-02 04:52:31.369 elif tag == 'insert':
2025-07-02 04:52:31.369 btags += '+' * lb
2025-07-02 04:52:31.369 elif tag == 'equal':
2025-07-02 04:52:31.369 atags += ' ' * la
2025-07-02 04:52:31.369 btags += ' ' * lb
2025-07-02 04:52:31.369 else:
2025-07-02 04:52:31.369 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.369 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.369 else:
2025-07-02 04:52:31.369 # the synch pair is identical
2025-07-02 04:52:31.369 yield ' ' + aelt
2025-07-02 04:52:31.370
2025-07-02 04:52:31.370 # pump out diffs from after the synch point
2025-07-02 04:52:31.370 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.370
2025-07-02 04:52:31.370 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.370 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.370
2025-07-02 04:52:31.370 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.370 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.370 alo = 32, ahi = 1101
2025-07-02 04:52:31.370 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.370 blo = 32, bhi = 1101
2025-07-02 04:52:31.370
2025-07-02 04:52:31.370 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.370 g = []
2025-07-02 04:52:31.370 if alo < ahi:
2025-07-02 04:52:31.370 if blo < bhi:
2025-07-02 04:52:31.370 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.370 else:
2025-07-02 04:52:31.370 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.371 elif blo < bhi:
2025-07-02 04:52:31.371 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.371
2025-07-02 04:52:31.371 > yield from g
2025-07-02 04:52:31.371
2025-07-02 04:52:31.371 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.371 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.371
2025-07-02 04:52:31.371 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.371 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.371 alo = 32, ahi = 1101
2025-07-02 04:52:31.371 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.371 blo = 32, bhi = 1101
2025-07-02 04:52:31.371
2025-07-02 04:52:31.371 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.371 r"""
2025-07-02 04:52:31.371 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.371 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.371 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.371 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.372
2025-07-02 04:52:31.372 Example:
2025-07-02 04:52:31.372
2025-07-02 04:52:31.372 >>> d = Differ()
2025-07-02 04:52:31.372 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.372 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.372 >>> print(''.join(results), end="")
2025-07-02 04:52:31.372 - abcDefghiJkl
2025-07-02 04:52:31.372 + abcdefGhijkl
2025-07-02 04:52:31.372 """
2025-07-02 04:52:31.372
2025-07-02 04:52:31.372 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.372 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.372 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.372 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.372 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.372
2025-07-02 04:52:31.372 # search for the pair that matches best without being identical
2025-07-02 04:52:31.373 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.373 # on junk -- unless we have to)
2025-07-02 04:52:31.373 for j in range(blo, bhi):
2025-07-02 04:52:31.373 bj = b[j]
2025-07-02 04:52:31.373 cruncher.set_seq2(bj)
2025-07-02 04:52:31.373 for i in range(alo, ahi):
2025-07-02 04:52:31.373 ai = a[i]
2025-07-02 04:52:31.373 if ai == bj:
2025-07-02 04:52:31.373 if eqi is None:
2025-07-02 04:52:31.373 eqi, eqj = i, j
2025-07-02 04:52:31.373 continue
2025-07-02 04:52:31.373 cruncher.set_seq1(ai)
2025-07-02 04:52:31.373 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.373 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.373 # compares by a factor of 3.
2025-07-02 04:52:31.373 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.373 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.373 # of the computation is cached by cruncher
2025-07-02 04:52:31.373 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.374 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.374 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.374 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.374 if best_ratio < cutoff:
2025-07-02 04:52:31.374 # no non-identical "pretty close" pair
2025-07-02 04:52:31.374 if eqi is None:
2025-07-02 04:52:31.374 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.374 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.374 return
2025-07-02 04:52:31.374 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.374 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.374 else:
2025-07-02 04:52:31.374 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.374 eqi = None
2025-07-02 04:52:31.374
2025-07-02 04:52:31.374 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.374 # identical
2025-07-02 04:52:31.374
2025-07-02 04:52:31.374 # pump out diffs from before the synch point
2025-07-02 04:52:31.374 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.374
2025-07-02 04:52:31.375 # do intraline marking on the synch pair
2025-07-02 04:52:31.375 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.375 if eqi is None:
2025-07-02 04:52:31.375 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.375 atags = btags = ""
2025-07-02 04:52:31.375 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.375 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.375 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.375 if tag == 'replace':
2025-07-02 04:52:31.375 atags += '^' * la
2025-07-02 04:52:31.375 btags += '^' * lb
2025-07-02 04:52:31.375 elif tag == 'delete':
2025-07-02 04:52:31.375 atags += '-' * la
2025-07-02 04:52:31.375 elif tag == 'insert':
2025-07-02 04:52:31.375 btags += '+' * lb
2025-07-02 04:52:31.375 elif tag == 'equal':
2025-07-02 04:52:31.375 atags += ' ' * la
2025-07-02 04:52:31.375 btags += ' ' * lb
2025-07-02 04:52:31.375 else:
2025-07-02 04:52:31.375 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.376 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.376 else:
2025-07-02 04:52:31.376 # the synch pair is identical
2025-07-02 04:52:31.376 yield ' ' + aelt
2025-07-02 04:52:31.376
2025-07-02 04:52:31.376 # pump out diffs from after the synch point
2025-07-02 04:52:31.376 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.376
2025-07-02 04:52:31.376 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.376 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.376
2025-07-02 04:52:31.376 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.376 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.376 alo = 33, ahi = 1101
2025-07-02 04:52:31.376 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.376 blo = 33, bhi = 1101
2025-07-02 04:52:31.376
2025-07-02 04:52:31.376 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.376 g = []
2025-07-02 04:52:31.377 if alo < ahi:
2025-07-02 04:52:31.377 if blo < bhi:
2025-07-02 04:52:31.377 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.377 else:
2025-07-02 04:52:31.377 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.377 elif blo < bhi:
2025-07-02 04:52:31.377 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.377
2025-07-02 04:52:31.377 > yield from g
2025-07-02 04:52:31.377
2025-07-02 04:52:31.377 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.377 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.377
2025-07-02 04:52:31.377 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.377 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.377 alo = 33, ahi = 1101
2025-07-02 04:52:31.377 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.377 blo = 33, bhi = 1101
2025-07-02 04:52:31.377
2025-07-02 04:52:31.377 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.378 r"""
2025-07-02 04:52:31.378 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.378 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.378 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.378 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.378
2025-07-02 04:52:31.378 Example:
2025-07-02 04:52:31.378
2025-07-02 04:52:31.378 >>> d = Differ()
2025-07-02 04:52:31.378 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.378 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.378 >>> print(''.join(results), end="")
2025-07-02 04:52:31.378 - abcDefghiJkl
2025-07-02 04:52:31.378 + abcdefGhijkl
2025-07-02 04:52:31.378 """
2025-07-02 04:52:31.378
2025-07-02 04:52:31.378 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.378 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.378 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.379 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.379 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.379
2025-07-02 04:52:31.379 # search for the pair that matches best without being identical
2025-07-02 04:52:31.379 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.379 # on junk -- unless we have to)
2025-07-02 04:52:31.379 for j in range(blo, bhi):
2025-07-02 04:52:31.379 bj = b[j]
2025-07-02 04:52:31.379 cruncher.set_seq2(bj)
2025-07-02 04:52:31.379 for i in range(alo, ahi):
2025-07-02 04:52:31.379 ai = a[i]
2025-07-02 04:52:31.379 if ai == bj:
2025-07-02 04:52:31.379 if eqi is None:
2025-07-02 04:52:31.379 eqi, eqj = i, j
2025-07-02 04:52:31.379 continue
2025-07-02 04:52:31.379 cruncher.set_seq1(ai)
2025-07-02 04:52:31.379 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.379 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.379 # compares by a factor of 3.
2025-07-02 04:52:31.379 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.380 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.380 # of the computation is cached by cruncher
2025-07-02 04:52:31.380 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.380 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.380 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.380 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.380 if best_ratio < cutoff:
2025-07-02 04:52:31.380 # no non-identical "pretty close" pair
2025-07-02 04:52:31.380 if eqi is None:
2025-07-02 04:52:31.380 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.380 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.380 return
2025-07-02 04:52:31.380 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.380 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.380 else:
2025-07-02 04:52:31.380 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.380 eqi = None
2025-07-02 04:52:31.380
2025-07-02 04:52:31.380 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.380 # identical
2025-07-02 04:52:31.381
2025-07-02 04:52:31.381 # pump out diffs from before the synch point
2025-07-02 04:52:31.381 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.381
2025-07-02 04:52:31.381 # do intraline marking on the synch pair
2025-07-02 04:52:31.381 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.381 if eqi is None:
2025-07-02 04:52:31.381 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.381 atags = btags = ""
2025-07-02 04:52:31.381 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.381 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.381 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.381 if tag == 'replace':
2025-07-02 04:52:31.381 atags += '^' * la
2025-07-02 04:52:31.381 btags += '^' * lb
2025-07-02 04:52:31.381 elif tag == 'delete':
2025-07-02 04:52:31.381 atags += '-' * la
2025-07-02 04:52:31.381 elif tag == 'insert':
2025-07-02 04:52:31.381 btags += '+' * lb
2025-07-02 04:52:31.381 elif tag == 'equal':
2025-07-02 04:52:31.382 atags += ' ' * la
2025-07-02 04:52:31.382 btags += ' ' * lb
2025-07-02 04:52:31.382 else:
2025-07-02 04:52:31.382 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.382 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.382 else:
2025-07-02 04:52:31.382 # the synch pair is identical
2025-07-02 04:52:31.382 yield ' ' + aelt
2025-07-02 04:52:31.382
2025-07-02 04:52:31.382 # pump out diffs from after the synch point
2025-07-02 04:52:31.382 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.382
2025-07-02 04:52:31.382 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.382 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.382
2025-07-02 04:52:31.382 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.382 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.382 alo = 34, ahi = 1101
2025-07-02 04:52:31.382 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.383 blo = 34, bhi = 1101
2025-07-02 04:52:31.383
2025-07-02 04:52:31.383 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.383 g = []
2025-07-02 04:52:31.383 if alo < ahi:
2025-07-02 04:52:31.383 if blo < bhi:
2025-07-02 04:52:31.383 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.383 else:
2025-07-02 04:52:31.383 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.383 elif blo < bhi:
2025-07-02 04:52:31.383 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.383
2025-07-02 04:52:31.383 > yield from g
2025-07-02 04:52:31.383
2025-07-02 04:52:31.383 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.383 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.383
2025-07-02 04:52:31.383 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.383 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.383 alo = 34, ahi = 1101
2025-07-02 04:52:31.383 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.384 blo = 34, bhi = 1101
2025-07-02 04:52:31.384
2025-07-02 04:52:31.384 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.384 r"""
2025-07-02 04:52:31.384 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.384 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.384 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.384 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.384
2025-07-02 04:52:31.384 Example:
2025-07-02 04:52:31.384
2025-07-02 04:52:31.384 >>> d = Differ()
2025-07-02 04:52:31.384 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.384 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.384 >>> print(''.join(results), end="")
2025-07-02 04:52:31.384 - abcDefghiJkl
2025-07-02 04:52:31.384 + abcdefGhijkl
2025-07-02 04:52:31.384 """
2025-07-02 04:52:31.385
2025-07-02 04:52:31.385 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.385 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.385 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.385 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.385 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.385
2025-07-02 04:52:31.385 # search for the pair that matches best without being identical
2025-07-02 04:52:31.385 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.385 # on junk -- unless we have to)
2025-07-02 04:52:31.385 for j in range(blo, bhi):
2025-07-02 04:52:31.385 bj = b[j]
2025-07-02 04:52:31.385 cruncher.set_seq2(bj)
2025-07-02 04:52:31.385 for i in range(alo, ahi):
2025-07-02 04:52:31.385 ai = a[i]
2025-07-02 04:52:31.385 if ai == bj:
2025-07-02 04:52:31.385 if eqi is None:
2025-07-02 04:52:31.385 eqi, eqj = i, j
2025-07-02 04:52:31.385 continue
2025-07-02 04:52:31.385 cruncher.set_seq1(ai)
2025-07-02 04:52:31.385 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.386 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.386 # compares by a factor of 3.
2025-07-02 04:52:31.386 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.386 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.386 # of the computation is cached by cruncher
2025-07-02 04:52:31.386 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.386 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.386 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.386 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.386 if best_ratio < cutoff:
2025-07-02 04:52:31.386 # no non-identical "pretty close" pair
2025-07-02 04:52:31.386 if eqi is None:
2025-07-02 04:52:31.386 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.386 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.386 return
2025-07-02 04:52:31.386 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.386 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.386 else:
2025-07-02 04:52:31.386 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.386 eqi = None
2025-07-02 04:52:31.387
2025-07-02 04:52:31.387 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.387 # identical
2025-07-02 04:52:31.387
2025-07-02 04:52:31.387 # pump out diffs from before the synch point
2025-07-02 04:52:31.387 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.387
2025-07-02 04:52:31.387 # do intraline marking on the synch pair
2025-07-02 04:52:31.387 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.387 if eqi is None:
2025-07-02 04:52:31.387 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.387 atags = btags = ""
2025-07-02 04:52:31.387 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.387 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.387 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.387 if tag == 'replace':
2025-07-02 04:52:31.387 atags += '^' * la
2025-07-02 04:52:31.387 btags += '^' * lb
2025-07-02 04:52:31.387 elif tag == 'delete':
2025-07-02 04:52:31.387 atags += '-' * la
2025-07-02 04:52:31.387 elif tag == 'insert':
2025-07-02 04:52:31.388 btags += '+' * lb
2025-07-02 04:52:31.388 elif tag == 'equal':
2025-07-02 04:52:31.388 atags += ' ' * la
2025-07-02 04:52:31.388 btags += ' ' * lb
2025-07-02 04:52:31.388 else:
2025-07-02 04:52:31.388 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.388 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.388 else:
2025-07-02 04:52:31.388 # the synch pair is identical
2025-07-02 04:52:31.388 yield ' ' + aelt
2025-07-02 04:52:31.388
2025-07-02 04:52:31.388 # pump out diffs from after the synch point
2025-07-02 04:52:31.388 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.388
2025-07-02 04:52:31.388 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.388 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.388
2025-07-02 04:52:31.388 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.388 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.388 alo = 35, ahi = 1101
2025-07-02 04:52:31.389 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.389 blo = 35, bhi = 1101
2025-07-02 04:52:31.389
2025-07-02 04:52:31.389 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.389 g = []
2025-07-02 04:52:31.389 if alo < ahi:
2025-07-02 04:52:31.389 if blo < bhi:
2025-07-02 04:52:31.389 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.389 else:
2025-07-02 04:52:31.389 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.389 elif blo < bhi:
2025-07-02 04:52:31.389 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.389
2025-07-02 04:52:31.389 > yield from g
2025-07-02 04:52:31.389
2025-07-02 04:52:31.389 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.389 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.389
2025-07-02 04:52:31.389 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.390 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.390 alo = 35, ahi = 1101
2025-07-02 04:52:31.390 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.390 blo = 35, bhi = 1101
2025-07-02 04:52:31.390
2025-07-02 04:52:31.390 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.390 r"""
2025-07-02 04:52:31.390 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.390 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.390 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.390 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.390
2025-07-02 04:52:31.390 Example:
2025-07-02 04:52:31.390
2025-07-02 04:52:31.390 >>> d = Differ()
2025-07-02 04:52:31.390 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.390 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.390 >>> print(''.join(results), end="")
2025-07-02 04:52:31.390 - abcDefghiJkl
2025-07-02 04:52:31.391 + abcdefGhijkl
2025-07-02 04:52:31.391 """
2025-07-02 04:52:31.391
2025-07-02 04:52:31.391 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.391 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.391 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.391 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.391 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.391
2025-07-02 04:52:31.391 # search for the pair that matches best without being identical
2025-07-02 04:52:31.391 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.391 # on junk -- unless we have to)
2025-07-02 04:52:31.391 for j in range(blo, bhi):
2025-07-02 04:52:31.391 bj = b[j]
2025-07-02 04:52:31.391 cruncher.set_seq2(bj)
2025-07-02 04:52:31.391 for i in range(alo, ahi):
2025-07-02 04:52:31.391 ai = a[i]
2025-07-02 04:52:31.391 if ai == bj:
2025-07-02 04:52:31.391 if eqi is None:
2025-07-02 04:52:31.392 eqi, eqj = i, j
2025-07-02 04:52:31.392 continue
2025-07-02 04:52:31.392 cruncher.set_seq1(ai)
2025-07-02 04:52:31.392 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.392 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.392 # compares by a factor of 3.
2025-07-02 04:52:31.392 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.392 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.392 # of the computation is cached by cruncher
2025-07-02 04:52:31.392 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.392 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.392 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.392 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.392 if best_ratio < cutoff:
2025-07-02 04:52:31.392 # no non-identical "pretty close" pair
2025-07-02 04:52:31.392 if eqi is None:
2025-07-02 04:52:31.392 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.392 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.393 return
2025-07-02 04:52:31.393 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.393 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.393 else:
2025-07-02 04:52:31.393 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.393 eqi = None
2025-07-02 04:52:31.393
2025-07-02 04:52:31.393 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.393 # identical
2025-07-02 04:52:31.393
2025-07-02 04:52:31.393 # pump out diffs from before the synch point
2025-07-02 04:52:31.393 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.393
2025-07-02 04:52:31.393 # do intraline marking on the synch pair
2025-07-02 04:52:31.393 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.393 if eqi is None:
2025-07-02 04:52:31.393 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.393 atags = btags = ""
2025-07-02 04:52:31.393 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.393 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.393 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.394 if tag == 'replace':
2025-07-02 04:52:31.394 atags += '^' * la
2025-07-02 04:52:31.394 btags += '^' * lb
2025-07-02 04:52:31.394 elif tag == 'delete':
2025-07-02 04:52:31.394 atags += '-' * la
2025-07-02 04:52:31.394 elif tag == 'insert':
2025-07-02 04:52:31.394 btags += '+' * lb
2025-07-02 04:52:31.394 elif tag == 'equal':
2025-07-02 04:52:31.394 atags += ' ' * la
2025-07-02 04:52:31.394 btags += ' ' * lb
2025-07-02 04:52:31.394 else:
2025-07-02 04:52:31.394 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.394 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.394 else:
2025-07-02 04:52:31.394 # the synch pair is identical
2025-07-02 04:52:31.394 yield ' ' + aelt
2025-07-02 04:52:31.394
2025-07-02 04:52:31.394 # pump out diffs from after the synch point
2025-07-02 04:52:31.394 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.394
2025-07-02 04:52:31.395 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.395 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.395
2025-07-02 04:52:31.395 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.395 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.395 alo = 36, ahi = 1101
2025-07-02 04:52:31.395 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.395 blo = 36, bhi = 1101
2025-07-02 04:52:31.395
2025-07-02 04:52:31.395 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.395 g = []
2025-07-02 04:52:31.395 if alo < ahi:
2025-07-02 04:52:31.395 if blo < bhi:
2025-07-02 04:52:31.395 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.395 else:
2025-07-02 04:52:31.395 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.395 elif blo < bhi:
2025-07-02 04:52:31.395 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.395
2025-07-02 04:52:31.395 > yield from g
2025-07-02 04:52:31.395
2025-07-02 04:52:31.396 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.396 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.396
2025-07-02 04:52:31.396 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.396 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.396 alo = 36, ahi = 1101
2025-07-02 04:52:31.396 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.396 blo = 36, bhi = 1101
2025-07-02 04:52:31.396
2025-07-02 04:52:31.396 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.396 r"""
2025-07-02 04:52:31.396 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.396 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.396 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.396 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.396
2025-07-02 04:52:31.396 Example:
2025-07-02 04:52:31.396
2025-07-02 04:52:31.396 >>> d = Differ()
2025-07-02 04:52:31.396 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.397 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.397 >>> print(''.join(results), end="")
2025-07-02 04:52:31.397 - abcDefghiJkl
2025-07-02 04:52:31.397 + abcdefGhijkl
2025-07-02 04:52:31.397 """
2025-07-02 04:52:31.397
2025-07-02 04:52:31.397 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.397 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.397 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.397 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.397 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.397
2025-07-02 04:52:31.397 # search for the pair that matches best without being identical
2025-07-02 04:52:31.397 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.397 # on junk -- unless we have to)
2025-07-02 04:52:31.397 for j in range(blo, bhi):
2025-07-02 04:52:31.397 bj = b[j]
2025-07-02 04:52:31.397 cruncher.set_seq2(bj)
2025-07-02 04:52:31.398 for i in range(alo, ahi):
2025-07-02 04:52:31.398 ai = a[i]
2025-07-02 04:52:31.398 if ai == bj:
2025-07-02 04:52:31.398 if eqi is None:
2025-07-02 04:52:31.398 eqi, eqj = i, j
2025-07-02 04:52:31.398 continue
2025-07-02 04:52:31.398 cruncher.set_seq1(ai)
2025-07-02 04:52:31.398 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.398 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.398 # compares by a factor of 3.
2025-07-02 04:52:31.398 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.398 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.398 # of the computation is cached by cruncher
2025-07-02 04:52:31.398 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.398 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.398 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.398 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.398 if best_ratio < cutoff:
2025-07-02 04:52:31.399 # no non-identical "pretty close" pair
2025-07-02 04:52:31.399 if eqi is None:
2025-07-02 04:52:31.399 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.399 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.399 return
2025-07-02 04:52:31.399 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.399 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.399 else:
2025-07-02 04:52:31.399 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.399 eqi = None
2025-07-02 04:52:31.399
2025-07-02 04:52:31.399 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.399 # identical
2025-07-02 04:52:31.399
2025-07-02 04:52:31.399 # pump out diffs from before the synch point
2025-07-02 04:52:31.399 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.399
2025-07-02 04:52:31.399 # do intraline marking on the synch pair
2025-07-02 04:52:31.399 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.399 if eqi is None:
2025-07-02 04:52:31.400 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.400 atags = btags = ""
2025-07-02 04:52:31.400 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.400 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.400 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.400 if tag == 'replace':
2025-07-02 04:52:31.400 atags += '^' * la
2025-07-02 04:52:31.400 btags += '^' * lb
2025-07-02 04:52:31.400 elif tag == 'delete':
2025-07-02 04:52:31.400 atags += '-' * la
2025-07-02 04:52:31.400 elif tag == 'insert':
2025-07-02 04:52:31.400 btags += '+' * lb
2025-07-02 04:52:31.400 elif tag == 'equal':
2025-07-02 04:52:31.400 atags += ' ' * la
2025-07-02 04:52:31.400 btags += ' ' * lb
2025-07-02 04:52:31.400 else:
2025-07-02 04:52:31.400 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.400 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.400 else:
2025-07-02 04:52:31.400 # the synch pair is identical
2025-07-02 04:52:31.400 yield ' ' + aelt
2025-07-02 04:52:31.401
2025-07-02 04:52:31.401 # pump out diffs from after the synch point
2025-07-02 04:52:31.401 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.401
2025-07-02 04:52:31.401 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.401 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.401
2025-07-02 04:52:31.401 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.401 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.401 alo = 37, ahi = 1101
2025-07-02 04:52:31.401 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.401 blo = 37, bhi = 1101
2025-07-02 04:52:31.401
2025-07-02 04:52:31.401 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.401 g = []
2025-07-02 04:52:31.401 if alo < ahi:
2025-07-02 04:52:31.401 if blo < bhi:
2025-07-02 04:52:31.401 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.401 else:
2025-07-02 04:52:31.401 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.402 elif blo < bhi:
2025-07-02 04:52:31.402 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.402
2025-07-02 04:52:31.402 > yield from g
2025-07-02 04:52:31.402
2025-07-02 04:52:31.402 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.402 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.402
2025-07-02 04:52:31.402 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.402 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.402 alo = 37, ahi = 1101
2025-07-02 04:52:31.402 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.402 blo = 37, bhi = 1101
2025-07-02 04:52:31.402
2025-07-02 04:52:31.402 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.402 r"""
2025-07-02 04:52:31.402 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.402 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.402 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.402 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.402
2025-07-02 04:52:31.403 Example:
2025-07-02 04:52:31.403
2025-07-02 04:52:31.403 >>> d = Differ()
2025-07-02 04:52:31.403 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.403 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.403 >>> print(''.join(results), end="")
2025-07-02 04:52:31.403 - abcDefghiJkl
2025-07-02 04:52:31.403 + abcdefGhijkl
2025-07-02 04:52:31.403 """
2025-07-02 04:52:31.403
2025-07-02 04:52:31.403 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.403 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.403 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.403 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.403 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.403
2025-07-02 04:52:31.403 # search for the pair that matches best without being identical
2025-07-02 04:52:31.403 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.404 # on junk -- unless we have to)
2025-07-02 04:52:31.404 for j in range(blo, bhi):
2025-07-02 04:52:31.404 bj = b[j]
2025-07-02 04:52:31.404 cruncher.set_seq2(bj)
2025-07-02 04:52:31.404 for i in range(alo, ahi):
2025-07-02 04:52:31.404 ai = a[i]
2025-07-02 04:52:31.404 if ai == bj:
2025-07-02 04:52:31.404 if eqi is None:
2025-07-02 04:52:31.404 eqi, eqj = i, j
2025-07-02 04:52:31.404 continue
2025-07-02 04:52:31.404 cruncher.set_seq1(ai)
2025-07-02 04:52:31.404 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.404 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.404 # compares by a factor of 3.
2025-07-02 04:52:31.404 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.404 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.404 # of the computation is cached by cruncher
2025-07-02 04:52:31.404 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.404 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.404 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.404 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.405 if best_ratio < cutoff:
2025-07-02 04:52:31.405 # no non-identical "pretty close" pair
2025-07-02 04:52:31.405 if eqi is None:
2025-07-02 04:52:31.405 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.405 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.405 return
2025-07-02 04:52:31.405 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.405 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.405 else:
2025-07-02 04:52:31.405 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.405 eqi = None
2025-07-02 04:52:31.405
2025-07-02 04:52:31.405 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.405 # identical
2025-07-02 04:52:31.405
2025-07-02 04:52:31.405 # pump out diffs from before the synch point
2025-07-02 04:52:31.405 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.405
2025-07-02 04:52:31.405 # do intraline marking on the synch pair
2025-07-02 04:52:31.405 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.405 if eqi is None:
2025-07-02 04:52:31.406 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.406 atags = btags = ""
2025-07-02 04:52:31.406 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.406 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.406 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.406 if tag == 'replace':
2025-07-02 04:52:31.406 atags += '^' * la
2025-07-02 04:52:31.406 btags += '^' * lb
2025-07-02 04:52:31.406 elif tag == 'delete':
2025-07-02 04:52:31.406 atags += '-' * la
2025-07-02 04:52:31.406 elif tag == 'insert':
2025-07-02 04:52:31.406 btags += '+' * lb
2025-07-02 04:52:31.406 elif tag == 'equal':
2025-07-02 04:52:31.406 atags += ' ' * la
2025-07-02 04:52:31.406 btags += ' ' * lb
2025-07-02 04:52:31.406 else:
2025-07-02 04:52:31.406 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.406 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.406 else:
2025-07-02 04:52:31.407 # the synch pair is identical
2025-07-02 04:52:31.407 yield ' ' + aelt
2025-07-02 04:52:31.407
2025-07-02 04:52:31.407 # pump out diffs from after the synch point
2025-07-02 04:52:31.407 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.407
2025-07-02 04:52:31.407 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.407 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.407
2025-07-02 04:52:31.407 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.407 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.407 alo = 38, ahi = 1101
2025-07-02 04:52:31.407 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.407 blo = 38, bhi = 1101
2025-07-02 04:52:31.407
2025-07-02 04:52:31.407 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.407 g = []
2025-07-02 04:52:31.407 if alo < ahi:
2025-07-02 04:52:31.407 if blo < bhi:
2025-07-02 04:52:31.407 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.408 else:
2025-07-02 04:52:31.408 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.408 elif blo < bhi:
2025-07-02 04:52:31.408 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.408
2025-07-02 04:52:31.408 > yield from g
2025-07-02 04:52:31.408
2025-07-02 04:52:31.408 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.408 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.408
2025-07-02 04:52:31.408 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.408 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.408 alo = 38, ahi = 1101
2025-07-02 04:52:31.408 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.408 blo = 38, bhi = 1101
2025-07-02 04:52:31.408
2025-07-02 04:52:31.408 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.408 r"""
2025-07-02 04:52:31.408 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.408 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.409 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.409 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.409
2025-07-02 04:52:31.409 Example:
2025-07-02 04:52:31.409
2025-07-02 04:52:31.409 >>> d = Differ()
2025-07-02 04:52:31.409 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.409 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.409 >>> print(''.join(results), end="")
2025-07-02 04:52:31.409 - abcDefghiJkl
2025-07-02 04:52:31.409 + abcdefGhijkl
2025-07-02 04:52:31.409 """
2025-07-02 04:52:31.409
2025-07-02 04:52:31.409 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.409 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.409 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.409 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.410 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.410
2025-07-02 04:52:31.410 # search for the pair that matches best without being identical
2025-07-02 04:52:31.410 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.410 # on junk -- unless we have to)
2025-07-02 04:52:31.410 for j in range(blo, bhi):
2025-07-02 04:52:31.410 bj = b[j]
2025-07-02 04:52:31.410 cruncher.set_seq2(bj)
2025-07-02 04:52:31.410 for i in range(alo, ahi):
2025-07-02 04:52:31.410 ai = a[i]
2025-07-02 04:52:31.410 if ai == bj:
2025-07-02 04:52:31.410 if eqi is None:
2025-07-02 04:52:31.410 eqi, eqj = i, j
2025-07-02 04:52:31.410 continue
2025-07-02 04:52:31.410 cruncher.set_seq1(ai)
2025-07-02 04:52:31.410 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.410 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.410 # compares by a factor of 3.
2025-07-02 04:52:31.410 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.410 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.411 # of the computation is cached by cruncher
2025-07-02 04:52:31.411 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.411 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.411 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.411 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.411 if best_ratio < cutoff:
2025-07-02 04:52:31.411 # no non-identical "pretty close" pair
2025-07-02 04:52:31.411 if eqi is None:
2025-07-02 04:52:31.411 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.411 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.411 return
2025-07-02 04:52:31.411 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.411 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.411 else:
2025-07-02 04:52:31.411 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.411 eqi = None
2025-07-02 04:52:31.411
2025-07-02 04:52:31.411 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.411 # identical
2025-07-02 04:52:31.411
2025-07-02 04:52:31.411 # pump out diffs from before the synch point
2025-07-02 04:52:31.412 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.412
2025-07-02 04:52:31.412 # do intraline marking on the synch pair
2025-07-02 04:52:31.412 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.412 if eqi is None:
2025-07-02 04:52:31.412 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.412 atags = btags = ""
2025-07-02 04:52:31.412 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.412 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.412 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.412 if tag == 'replace':
2025-07-02 04:52:31.412 atags += '^' * la
2025-07-02 04:52:31.412 btags += '^' * lb
2025-07-02 04:52:31.412 elif tag == 'delete':
2025-07-02 04:52:31.412 atags += '-' * la
2025-07-02 04:52:31.412 elif tag == 'insert':
2025-07-02 04:52:31.412 btags += '+' * lb
2025-07-02 04:52:31.412 elif tag == 'equal':
2025-07-02 04:52:31.412 atags += ' ' * la
2025-07-02 04:52:31.412 btags += ' ' * lb
2025-07-02 04:52:31.413 else:
2025-07-02 04:52:31.413 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.413 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.413 else:
2025-07-02 04:52:31.413 # the synch pair is identical
2025-07-02 04:52:31.413 yield ' ' + aelt
2025-07-02 04:52:31.413
2025-07-02 04:52:31.413 # pump out diffs from after the synch point
2025-07-02 04:52:31.413 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.413
2025-07-02 04:52:31.413 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.413 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.413
2025-07-02 04:52:31.413 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.413 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.413 alo = 39, ahi = 1101
2025-07-02 04:52:31.413 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.413 blo = 39, bhi = 1101
2025-07-02 04:52:31.413
2025-07-02 04:52:31.413 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.414 g = []
2025-07-02 04:52:31.414 if alo < ahi:
2025-07-02 04:52:31.414 if blo < bhi:
2025-07-02 04:52:31.414 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.414 else:
2025-07-02 04:52:31.414 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.414 elif blo < bhi:
2025-07-02 04:52:31.414 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.414
2025-07-02 04:52:31.414 > yield from g
2025-07-02 04:52:31.414
2025-07-02 04:52:31.414 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.414 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.414
2025-07-02 04:52:31.414 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.414 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.414 alo = 39, ahi = 1101
2025-07-02 04:52:31.414 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.414 blo = 39, bhi = 1101
2025-07-02 04:52:31.414
2025-07-02 04:52:31.414 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.415 r"""
2025-07-02 04:52:31.415 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.415 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.415 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.415 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.415
2025-07-02 04:52:31.415 Example:
2025-07-02 04:52:31.415
2025-07-02 04:52:31.415 >>> d = Differ()
2025-07-02 04:52:31.415 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.415 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.415 >>> print(''.join(results), end="")
2025-07-02 04:52:31.415 - abcDefghiJkl
2025-07-02 04:52:31.415 + abcdefGhijkl
2025-07-02 04:52:31.415 """
2025-07-02 04:52:31.415
2025-07-02 04:52:31.415 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.415 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.416 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.416 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.416 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.416
2025-07-02 04:52:31.416 # search for the pair that matches best without being identical
2025-07-02 04:52:31.416 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.416 # on junk -- unless we have to)
2025-07-02 04:52:31.416 for j in range(blo, bhi):
2025-07-02 04:52:31.416 bj = b[j]
2025-07-02 04:52:31.416 cruncher.set_seq2(bj)
2025-07-02 04:52:31.416 for i in range(alo, ahi):
2025-07-02 04:52:31.416 ai = a[i]
2025-07-02 04:52:31.416 if ai == bj:
2025-07-02 04:52:31.416 if eqi is None:
2025-07-02 04:52:31.416 eqi, eqj = i, j
2025-07-02 04:52:31.416 continue
2025-07-02 04:52:31.416 cruncher.set_seq1(ai)
2025-07-02 04:52:31.416 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.416 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.416 # compares by a factor of 3.
2025-07-02 04:52:31.417 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.417 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.417 # of the computation is cached by cruncher
2025-07-02 04:52:31.417 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.417 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.417 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.417 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.417 if best_ratio < cutoff:
2025-07-02 04:52:31.417 # no non-identical "pretty close" pair
2025-07-02 04:52:31.417 if eqi is None:
2025-07-02 04:52:31.417 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.417 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.417 return
2025-07-02 04:52:31.417 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.417 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.417 else:
2025-07-02 04:52:31.417 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.417 eqi = None
2025-07-02 04:52:31.417
2025-07-02 04:52:31.417 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.417 # identical
2025-07-02 04:52:31.418
2025-07-02 04:52:31.418 # pump out diffs from before the synch point
2025-07-02 04:52:31.418 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.418
2025-07-02 04:52:31.418 # do intraline marking on the synch pair
2025-07-02 04:52:31.418 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.418 if eqi is None:
2025-07-02 04:52:31.418 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.418 atags = btags = ""
2025-07-02 04:52:31.418 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.418 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.418 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.418 if tag == 'replace':
2025-07-02 04:52:31.418 atags += '^' * la
2025-07-02 04:52:31.418 btags += '^' * lb
2025-07-02 04:52:31.418 elif tag == 'delete':
2025-07-02 04:52:31.418 atags += '-' * la
2025-07-02 04:52:31.418 elif tag == 'insert':
2025-07-02 04:52:31.418 btags += '+' * lb
2025-07-02 04:52:31.418 elif tag == 'equal':
2025-07-02 04:52:31.419 atags += ' ' * la
2025-07-02 04:52:31.419 btags += ' ' * lb
2025-07-02 04:52:31.419 else:
2025-07-02 04:52:31.419 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.419 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.419 else:
2025-07-02 04:52:31.419 # the synch pair is identical
2025-07-02 04:52:31.419 yield ' ' + aelt
2025-07-02 04:52:31.419
2025-07-02 04:52:31.419 # pump out diffs from after the synch point
2025-07-02 04:52:31.419 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.419
2025-07-02 04:52:31.419 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.419 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.419
2025-07-02 04:52:31.419 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.419 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.419 alo = 40, ahi = 1101
2025-07-02 04:52:31.419 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.419 blo = 40, bhi = 1101
2025-07-02 04:52:31.419
2025-07-02 04:52:31.420 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.420 g = []
2025-07-02 04:52:31.420 if alo < ahi:
2025-07-02 04:52:31.420 if blo < bhi:
2025-07-02 04:52:31.420 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.420 else:
2025-07-02 04:52:31.420 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.420 elif blo < bhi:
2025-07-02 04:52:31.420 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.420
2025-07-02 04:52:31.420 > yield from g
2025-07-02 04:52:31.420
2025-07-02 04:52:31.420 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.420 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.420
2025-07-02 04:52:31.420 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.420 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.420 alo = 40, ahi = 1101
2025-07-02 04:52:31.420 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.420 blo = 40, bhi = 1101
2025-07-02 04:52:31.421
2025-07-02 04:52:31.421 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.421 r"""
2025-07-02 04:52:31.421 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.421 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.421 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.421 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.421
2025-07-02 04:52:31.421 Example:
2025-07-02 04:52:31.421
2025-07-02 04:52:31.421 >>> d = Differ()
2025-07-02 04:52:31.421 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.421 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.421 >>> print(''.join(results), end="")
2025-07-02 04:52:31.421 - abcDefghiJkl
2025-07-02 04:52:31.421 + abcdefGhijkl
2025-07-02 04:52:31.421 """
2025-07-02 04:52:31.421
2025-07-02 04:52:31.421 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.422 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.422 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.422 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.422 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.422
2025-07-02 04:52:31.422 # search for the pair that matches best without being identical
2025-07-02 04:52:31.422 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.422 # on junk -- unless we have to)
2025-07-02 04:52:31.422 for j in range(blo, bhi):
2025-07-02 04:52:31.422 bj = b[j]
2025-07-02 04:52:31.422 cruncher.set_seq2(bj)
2025-07-02 04:52:31.422 for i in range(alo, ahi):
2025-07-02 04:52:31.422 ai = a[i]
2025-07-02 04:52:31.422 if ai == bj:
2025-07-02 04:52:31.422 if eqi is None:
2025-07-02 04:52:31.422 eqi, eqj = i, j
2025-07-02 04:52:31.422 continue
2025-07-02 04:52:31.422 cruncher.set_seq1(ai)
2025-07-02 04:52:31.422 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.422 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.422 # compares by a factor of 3.
2025-07-02 04:52:31.423 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.423 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.423 # of the computation is cached by cruncher
2025-07-02 04:52:31.423 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.423 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.423 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.423 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.423 if best_ratio < cutoff:
2025-07-02 04:52:31.423 # no non-identical "pretty close" pair
2025-07-02 04:52:31.423 if eqi is None:
2025-07-02 04:52:31.423 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.423 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.423 return
2025-07-02 04:52:31.423 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.423 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.423 else:
2025-07-02 04:52:31.423 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.423 eqi = None
2025-07-02 04:52:31.423
2025-07-02 04:52:31.423 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.424 # identical
2025-07-02 04:52:31.424
2025-07-02 04:52:31.424 # pump out diffs from before the synch point
2025-07-02 04:52:31.424 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.424
2025-07-02 04:52:31.424 # do intraline marking on the synch pair
2025-07-02 04:52:31.424 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.424 if eqi is None:
2025-07-02 04:52:31.424 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.424 atags = btags = ""
2025-07-02 04:52:31.424 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.424 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.424 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.424 if tag == 'replace':
2025-07-02 04:52:31.424 atags += '^' * la
2025-07-02 04:52:31.424 btags += '^' * lb
2025-07-02 04:52:31.424 elif tag == 'delete':
2025-07-02 04:52:31.424 atags += '-' * la
2025-07-02 04:52:31.424 elif tag == 'insert':
2025-07-02 04:52:31.425 btags += '+' * lb
2025-07-02 04:52:31.425 elif tag == 'equal':
2025-07-02 04:52:31.425 atags += ' ' * la
2025-07-02 04:52:31.425 btags += ' ' * lb
2025-07-02 04:52:31.425 else:
2025-07-02 04:52:31.425 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.425 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.425 else:
2025-07-02 04:52:31.425 # the synch pair is identical
2025-07-02 04:52:31.425 yield ' ' + aelt
2025-07-02 04:52:31.425
2025-07-02 04:52:31.425 # pump out diffs from after the synch point
2025-07-02 04:52:31.425 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.425
2025-07-02 04:52:31.425 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.425 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.425
2025-07-02 04:52:31.425 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.425 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.425 alo = 41, ahi = 1101
2025-07-02 04:52:31.425 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.426 blo = 41, bhi = 1101
2025-07-02 04:52:31.426
2025-07-02 04:52:31.426 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.426 g = []
2025-07-02 04:52:31.426 if alo < ahi:
2025-07-02 04:52:31.426 if blo < bhi:
2025-07-02 04:52:31.426 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.426 else:
2025-07-02 04:52:31.426 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.426 elif blo < bhi:
2025-07-02 04:52:31.426 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.426
2025-07-02 04:52:31.426 > yield from g
2025-07-02 04:52:31.426
2025-07-02 04:52:31.426 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.426 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.426
2025-07-02 04:52:31.426 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.426 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.426 alo = 41, ahi = 1101
2025-07-02 04:52:31.426 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.427 blo = 41, bhi = 1101
2025-07-02 04:52:31.427
2025-07-02 04:52:31.427 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.427 r"""
2025-07-02 04:52:31.427 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.427 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.427 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.427 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.427
2025-07-02 04:52:31.427 Example:
2025-07-02 04:52:31.427
2025-07-02 04:52:31.427 >>> d = Differ()
2025-07-02 04:52:31.427 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.427 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.427 >>> print(''.join(results), end="")
2025-07-02 04:52:31.427 - abcDefghiJkl
2025-07-02 04:52:31.427 + abcdefGhijkl
2025-07-02 04:52:31.427 """
2025-07-02 04:52:31.427
2025-07-02 04:52:31.427 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.428 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.428 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.428 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.428 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.428
2025-07-02 04:52:31.428 # search for the pair that matches best without being identical
2025-07-02 04:52:31.428 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.428 # on junk -- unless we have to)
2025-07-02 04:52:31.428 for j in range(blo, bhi):
2025-07-02 04:52:31.428 bj = b[j]
2025-07-02 04:52:31.428 cruncher.set_seq2(bj)
2025-07-02 04:52:31.428 for i in range(alo, ahi):
2025-07-02 04:52:31.428 ai = a[i]
2025-07-02 04:52:31.428 if ai == bj:
2025-07-02 04:52:31.428 if eqi is None:
2025-07-02 04:52:31.428 eqi, eqj = i, j
2025-07-02 04:52:31.428 continue
2025-07-02 04:52:31.428 cruncher.set_seq1(ai)
2025-07-02 04:52:31.428 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.428 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.428 # compares by a factor of 3.
2025-07-02 04:52:31.429 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.429 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.429 # of the computation is cached by cruncher
2025-07-02 04:52:31.429 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.429 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.429 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.429 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.429 if best_ratio < cutoff:
2025-07-02 04:52:31.429 # no non-identical "pretty close" pair
2025-07-02 04:52:31.429 if eqi is None:
2025-07-02 04:52:31.429 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.429 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.429 return
2025-07-02 04:52:31.429 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.429 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.429 else:
2025-07-02 04:52:31.429 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.429 eqi = None
2025-07-02 04:52:31.429
2025-07-02 04:52:31.429 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.429 # identical
2025-07-02 04:52:31.429
2025-07-02 04:52:31.430 # pump out diffs from before the synch point
2025-07-02 04:52:31.430 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.430
2025-07-02 04:52:31.430 # do intraline marking on the synch pair
2025-07-02 04:52:31.430 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.430 if eqi is None:
2025-07-02 04:52:31.430 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.430 atags = btags = ""
2025-07-02 04:52:31.430 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.430 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.430 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.430 if tag == 'replace':
2025-07-02 04:52:31.430 atags += '^' * la
2025-07-02 04:52:31.430 btags += '^' * lb
2025-07-02 04:52:31.430 elif tag == 'delete':
2025-07-02 04:52:31.430 atags += '-' * la
2025-07-02 04:52:31.430 elif tag == 'insert':
2025-07-02 04:52:31.430 btags += '+' * lb
2025-07-02 04:52:31.430 elif tag == 'equal':
2025-07-02 04:52:31.430 atags += ' ' * la
2025-07-02 04:52:31.430 btags += ' ' * lb
2025-07-02 04:52:31.431 else:
2025-07-02 04:52:31.431 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.431 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.431 else:
2025-07-02 04:52:31.431 # the synch pair is identical
2025-07-02 04:52:31.431 yield ' ' + aelt
2025-07-02 04:52:31.431
2025-07-02 04:52:31.431 # pump out diffs from after the synch point
2025-07-02 04:52:31.431 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.431
2025-07-02 04:52:31.431 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.431 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.431
2025-07-02 04:52:31.431 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.431 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.431 alo = 42, ahi = 1101
2025-07-02 04:52:31.431 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.431 blo = 42, bhi = 1101
2025-07-02 04:52:31.431
2025-07-02 04:52:31.432 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.432 g = []
2025-07-02 04:52:31.432 if alo < ahi:
2025-07-02 04:52:31.432 if blo < bhi:
2025-07-02 04:52:31.432 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.432 else:
2025-07-02 04:52:31.432 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.432 elif blo < bhi:
2025-07-02 04:52:31.432 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.432
2025-07-02 04:52:31.432 > yield from g
2025-07-02 04:52:31.432
2025-07-02 04:52:31.432 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.432 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.432
2025-07-02 04:52:31.432 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.432 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.432 alo = 42, ahi = 1101
2025-07-02 04:52:31.432 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.432 blo = 42, bhi = 1101
2025-07-02 04:52:31.433
2025-07-02 04:52:31.433 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.433 r"""
2025-07-02 04:52:31.433 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.433 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.433 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.433 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.433
2025-07-02 04:52:31.433 Example:
2025-07-02 04:52:31.433
2025-07-02 04:52:31.433 >>> d = Differ()
2025-07-02 04:52:31.433 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.433 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.433 >>> print(''.join(results), end="")
2025-07-02 04:52:31.433 - abcDefghiJkl
2025-07-02 04:52:31.433 + abcdefGhijkl
2025-07-02 04:52:31.433 """
2025-07-02 04:52:31.433
2025-07-02 04:52:31.434 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.434 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.434 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.434 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.434 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.434
2025-07-02 04:52:31.434 # search for the pair that matches best without being identical
2025-07-02 04:52:31.434 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.434 # on junk -- unless we have to)
2025-07-02 04:52:31.434 for j in range(blo, bhi):
2025-07-02 04:52:31.434 bj = b[j]
2025-07-02 04:52:31.434 cruncher.set_seq2(bj)
2025-07-02 04:52:31.434 for i in range(alo, ahi):
2025-07-02 04:52:31.434 ai = a[i]
2025-07-02 04:52:31.434 if ai == bj:
2025-07-02 04:52:31.434 if eqi is None:
2025-07-02 04:52:31.434 eqi, eqj = i, j
2025-07-02 04:52:31.434 continue
2025-07-02 04:52:31.434 cruncher.set_seq1(ai)
2025-07-02 04:52:31.434 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.434 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.435 # compares by a factor of 3.
2025-07-02 04:52:31.435 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.435 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.435 # of the computation is cached by cruncher
2025-07-02 04:52:31.435 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.435 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.435 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.435 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.435 if best_ratio < cutoff:
2025-07-02 04:52:31.435 # no non-identical "pretty close" pair
2025-07-02 04:52:31.435 if eqi is None:
2025-07-02 04:52:31.435 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.435 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.435 return
2025-07-02 04:52:31.435 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.435 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.435 else:
2025-07-02 04:52:31.435 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.435 eqi = None
2025-07-02 04:52:31.435
2025-07-02 04:52:31.436 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.436 # identical
2025-07-02 04:52:31.436
2025-07-02 04:52:31.436 # pump out diffs from before the synch point
2025-07-02 04:52:31.436 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.436
2025-07-02 04:52:31.436 # do intraline marking on the synch pair
2025-07-02 04:52:31.436 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.436 if eqi is None:
2025-07-02 04:52:31.436 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.436 atags = btags = ""
2025-07-02 04:52:31.436 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.436 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.436 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.436 if tag == 'replace':
2025-07-02 04:52:31.436 atags += '^' * la
2025-07-02 04:52:31.436 btags += '^' * lb
2025-07-02 04:52:31.436 elif tag == 'delete':
2025-07-02 04:52:31.436 atags += '-' * la
2025-07-02 04:52:31.436 elif tag == 'insert':
2025-07-02 04:52:31.436 btags += '+' * lb
2025-07-02 04:52:31.437 elif tag == 'equal':
2025-07-02 04:52:31.437 atags += ' ' * la
2025-07-02 04:52:31.437 btags += ' ' * lb
2025-07-02 04:52:31.437 else:
2025-07-02 04:52:31.437 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.437 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.437 else:
2025-07-02 04:52:31.437 # the synch pair is identical
2025-07-02 04:52:31.437 yield ' ' + aelt
2025-07-02 04:52:31.437
2025-07-02 04:52:31.437 # pump out diffs from after the synch point
2025-07-02 04:52:31.437 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.437
2025-07-02 04:52:31.437 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.437 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.437
2025-07-02 04:52:31.437 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.437 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.437 alo = 43, ahi = 1101
2025-07-02 04:52:31.437 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.438 blo = 43, bhi = 1101
2025-07-02 04:52:31.438
2025-07-02 04:52:31.438 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.438 g = []
2025-07-02 04:52:31.438 if alo < ahi:
2025-07-02 04:52:31.438 if blo < bhi:
2025-07-02 04:52:31.438 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.438 else:
2025-07-02 04:52:31.438 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.438 elif blo < bhi:
2025-07-02 04:52:31.438 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.438
2025-07-02 04:52:31.438 > yield from g
2025-07-02 04:52:31.438
2025-07-02 04:52:31.438 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.438 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.438
2025-07-02 04:52:31.438 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.438 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.438 alo = 43, ahi = 1101
2025-07-02 04:52:31.438 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.439 blo = 43, bhi = 1101
2025-07-02 04:52:31.439
2025-07-02 04:52:31.439 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.439 r"""
2025-07-02 04:52:31.439 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.439 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.439 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.439 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.439
2025-07-02 04:52:31.439 Example:
2025-07-02 04:52:31.439
2025-07-02 04:52:31.439 >>> d = Differ()
2025-07-02 04:52:31.439 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.439 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.439 >>> print(''.join(results), end="")
2025-07-02 04:52:31.439 - abcDefghiJkl
2025-07-02 04:52:31.439 + abcdefGhijkl
2025-07-02 04:52:31.440 """
2025-07-02 04:52:31.440
2025-07-02 04:52:31.440 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.440 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.440 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.440 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.440 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.440
2025-07-02 04:52:31.440 # search for the pair that matches best without being identical
2025-07-02 04:52:31.440 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.440 # on junk -- unless we have to)
2025-07-02 04:52:31.440 for j in range(blo, bhi):
2025-07-02 04:52:31.440 bj = b[j]
2025-07-02 04:52:31.440 cruncher.set_seq2(bj)
2025-07-02 04:52:31.440 for i in range(alo, ahi):
2025-07-02 04:52:31.440 ai = a[i]
2025-07-02 04:52:31.440 if ai == bj:
2025-07-02 04:52:31.440 if eqi is None:
2025-07-02 04:52:31.440 eqi, eqj = i, j
2025-07-02 04:52:31.441 continue
2025-07-02 04:52:31.441 cruncher.set_seq1(ai)
2025-07-02 04:52:31.441 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.441 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.441 # compares by a factor of 3.
2025-07-02 04:52:31.441 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.441 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.441 # of the computation is cached by cruncher
2025-07-02 04:52:31.441 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.441 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.441 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.441 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.441 if best_ratio < cutoff:
2025-07-02 04:52:31.441 # no non-identical "pretty close" pair
2025-07-02 04:52:31.441 if eqi is None:
2025-07-02 04:52:31.441 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.441 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.441 return
2025-07-02 04:52:31.441 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.441 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.442 else:
2025-07-02 04:52:31.442 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.442 eqi = None
2025-07-02 04:52:31.442
2025-07-02 04:52:31.442 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.442 # identical
2025-07-02 04:52:31.442
2025-07-02 04:52:31.442 # pump out diffs from before the synch point
2025-07-02 04:52:31.442 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.442
2025-07-02 04:52:31.442 # do intraline marking on the synch pair
2025-07-02 04:52:31.442 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.442 if eqi is None:
2025-07-02 04:52:31.442 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.442 atags = btags = ""
2025-07-02 04:52:31.442 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.442 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.442 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.442 if tag == 'replace':
2025-07-02 04:52:31.442 atags += '^' * la
2025-07-02 04:52:31.442 btags += '^' * lb
2025-07-02 04:52:31.443 elif tag == 'delete':
2025-07-02 04:52:31.443 atags += '-' * la
2025-07-02 04:52:31.443 elif tag == 'insert':
2025-07-02 04:52:31.443 btags += '+' * lb
2025-07-02 04:52:31.443 elif tag == 'equal':
2025-07-02 04:52:31.443 atags += ' ' * la
2025-07-02 04:52:31.443 btags += ' ' * lb
2025-07-02 04:52:31.443 else:
2025-07-02 04:52:31.443 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.443 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.443 else:
2025-07-02 04:52:31.443 # the synch pair is identical
2025-07-02 04:52:31.443 yield ' ' + aelt
2025-07-02 04:52:31.443
2025-07-02 04:52:31.443 # pump out diffs from after the synch point
2025-07-02 04:52:31.443 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.443
2025-07-02 04:52:31.443 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.443 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.443
2025-07-02 04:52:31.443 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.444 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.444 alo = 44, ahi = 1101
2025-07-02 04:52:31.444 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.444 blo = 44, bhi = 1101
2025-07-02 04:52:31.444
2025-07-02 04:52:31.444 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.444 g = []
2025-07-02 04:52:31.444 if alo < ahi:
2025-07-02 04:52:31.444 if blo < bhi:
2025-07-02 04:52:31.444 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.444 else:
2025-07-02 04:52:31.444 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.444 elif blo < bhi:
2025-07-02 04:52:31.444 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.444
2025-07-02 04:52:31.444 > yield from g
2025-07-02 04:52:31.444
2025-07-02 04:52:31.444 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.444 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.444
2025-07-02 04:52:31.444 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.445 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.445 alo = 44, ahi = 1101
2025-07-02 04:52:31.445 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.445 blo = 44, bhi = 1101
2025-07-02 04:52:31.445
2025-07-02 04:52:31.445 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.445 r"""
2025-07-02 04:52:31.445 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.445 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.445 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.445 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.445
2025-07-02 04:52:31.445 Example:
2025-07-02 04:52:31.445
2025-07-02 04:52:31.445 >>> d = Differ()
2025-07-02 04:52:31.445 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.445 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.445 >>> print(''.join(results), end="")
2025-07-02 04:52:31.445 - abcDefghiJkl
2025-07-02 04:52:31.446 + abcdefGhijkl
2025-07-02 04:52:31.446 """
2025-07-02 04:52:31.446
2025-07-02 04:52:31.446 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.446 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.446 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.446 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.446 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.446
2025-07-02 04:52:31.446 # search for the pair that matches best without being identical
2025-07-02 04:52:31.446 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.446 # on junk -- unless we have to)
2025-07-02 04:52:31.446 for j in range(blo, bhi):
2025-07-02 04:52:31.446 bj = b[j]
2025-07-02 04:52:31.446 cruncher.set_seq2(bj)
2025-07-02 04:52:31.446 for i in range(alo, ahi):
2025-07-02 04:52:31.446 ai = a[i]
2025-07-02 04:52:31.446 if ai == bj:
2025-07-02 04:52:31.446 if eqi is None:
2025-07-02 04:52:31.446 eqi, eqj = i, j
2025-07-02 04:52:31.447 continue
2025-07-02 04:52:31.447 cruncher.set_seq1(ai)
2025-07-02 04:52:31.447 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.447 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.447 # compares by a factor of 3.
2025-07-02 04:52:31.447 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.447 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.447 # of the computation is cached by cruncher
2025-07-02 04:52:31.447 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.447 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.447 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.447 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.447 if best_ratio < cutoff:
2025-07-02 04:52:31.447 # no non-identical "pretty close" pair
2025-07-02 04:52:31.447 if eqi is None:
2025-07-02 04:52:31.447 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.447 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.447 return
2025-07-02 04:52:31.447 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.447 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.448 else:
2025-07-02 04:52:31.448 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.448 eqi = None
2025-07-02 04:52:31.448
2025-07-02 04:52:31.448 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.448 # identical
2025-07-02 04:52:31.448
2025-07-02 04:52:31.448 # pump out diffs from before the synch point
2025-07-02 04:52:31.448 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.448
2025-07-02 04:52:31.448 # do intraline marking on the synch pair
2025-07-02 04:52:31.448 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.448 if eqi is None:
2025-07-02 04:52:31.448 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.448 atags = btags = ""
2025-07-02 04:52:31.448 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.448 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.448 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.448 if tag == 'replace':
2025-07-02 04:52:31.449 atags += '^' * la
2025-07-02 04:52:31.449 btags += '^' * lb
2025-07-02 04:52:31.449 elif tag == 'delete':
2025-07-02 04:52:31.449 atags += '-' * la
2025-07-02 04:52:31.449 elif tag == 'insert':
2025-07-02 04:52:31.449 btags += '+' * lb
2025-07-02 04:52:31.449 elif tag == 'equal':
2025-07-02 04:52:31.449 atags += ' ' * la
2025-07-02 04:52:31.449 btags += ' ' * lb
2025-07-02 04:52:31.449 else:
2025-07-02 04:52:31.449 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.449 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.449 else:
2025-07-02 04:52:31.449 # the synch pair is identical
2025-07-02 04:52:31.449 yield ' ' + aelt
2025-07-02 04:52:31.449
2025-07-02 04:52:31.449 # pump out diffs from after the synch point
2025-07-02 04:52:31.449 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.449
2025-07-02 04:52:31.449 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.449 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.450
2025-07-02 04:52:31.450 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.450 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.450 alo = 45, ahi = 1101
2025-07-02 04:52:31.450 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.450 blo = 45, bhi = 1101
2025-07-02 04:52:31.450
2025-07-02 04:52:31.450 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.450 g = []
2025-07-02 04:52:31.450 if alo < ahi:
2025-07-02 04:52:31.450 if blo < bhi:
2025-07-02 04:52:31.450 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.450 else:
2025-07-02 04:52:31.450 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.450 elif blo < bhi:
2025-07-02 04:52:31.450 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.450
2025-07-02 04:52:31.450 > yield from g
2025-07-02 04:52:31.450
2025-07-02 04:52:31.450 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.450 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.451
2025-07-02 04:52:31.451 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.451 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.451 alo = 45, ahi = 1101
2025-07-02 04:52:31.451 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.451 blo = 45, bhi = 1101
2025-07-02 04:52:31.451
2025-07-02 04:52:31.451 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.451 r"""
2025-07-02 04:52:31.451 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.451 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.451 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.451 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.451
2025-07-02 04:52:31.451 Example:
2025-07-02 04:52:31.451
2025-07-02 04:52:31.451 >>> d = Differ()
2025-07-02 04:52:31.451 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.451 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.451 >>> print(''.join(results), end="")
2025-07-02 04:52:31.452 - abcDefghiJkl
2025-07-02 04:52:31.452 + abcdefGhijkl
2025-07-02 04:52:31.452 """
2025-07-02 04:52:31.452
2025-07-02 04:52:31.452 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.452 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.452 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.452 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.452 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.452
2025-07-02 04:52:31.452 # search for the pair that matches best without being identical
2025-07-02 04:52:31.452 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.452 # on junk -- unless we have to)
2025-07-02 04:52:31.452 for j in range(blo, bhi):
2025-07-02 04:52:31.452 bj = b[j]
2025-07-02 04:52:31.452 cruncher.set_seq2(bj)
2025-07-02 04:52:31.452 for i in range(alo, ahi):
2025-07-02 04:52:31.452 ai = a[i]
2025-07-02 04:52:31.453 if ai == bj:
2025-07-02 04:52:31.453 if eqi is None:
2025-07-02 04:52:31.453 eqi, eqj = i, j
2025-07-02 04:52:31.453 continue
2025-07-02 04:52:31.453 cruncher.set_seq1(ai)
2025-07-02 04:52:31.453 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.453 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.453 # compares by a factor of 3.
2025-07-02 04:52:31.453 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.453 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.453 # of the computation is cached by cruncher
2025-07-02 04:52:31.453 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.453 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.453 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.453 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.453 if best_ratio < cutoff:
2025-07-02 04:52:31.453 # no non-identical "pretty close" pair
2025-07-02 04:52:31.453 if eqi is None:
2025-07-02 04:52:31.453 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.453 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.453 return
2025-07-02 04:52:31.454 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.454 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.454 else:
2025-07-02 04:52:31.454 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.454 eqi = None
2025-07-02 04:52:31.454
2025-07-02 04:52:31.454 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.454 # identical
2025-07-02 04:52:31.454
2025-07-02 04:52:31.454 # pump out diffs from before the synch point
2025-07-02 04:52:31.454 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.454
2025-07-02 04:52:31.454 # do intraline marking on the synch pair
2025-07-02 04:52:31.454 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.454 if eqi is None:
2025-07-02 04:52:31.454 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.454 atags = btags = ""
2025-07-02 04:52:31.454 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.454 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.454 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.455 if tag == 'replace':
2025-07-02 04:52:31.455 atags += '^' * la
2025-07-02 04:52:31.455 btags += '^' * lb
2025-07-02 04:52:31.455 elif tag == 'delete':
2025-07-02 04:52:31.455 atags += '-' * la
2025-07-02 04:52:31.455 elif tag == 'insert':
2025-07-02 04:52:31.455 btags += '+' * lb
2025-07-02 04:52:31.455 elif tag == 'equal':
2025-07-02 04:52:31.455 atags += ' ' * la
2025-07-02 04:52:31.455 btags += ' ' * lb
2025-07-02 04:52:31.455 else:
2025-07-02 04:52:31.455 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.455 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.455 else:
2025-07-02 04:52:31.455 # the synch pair is identical
2025-07-02 04:52:31.455 yield ' ' + aelt
2025-07-02 04:52:31.455
2025-07-02 04:52:31.455 # pump out diffs from after the synch point
2025-07-02 04:52:31.455 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.456
2025-07-02 04:52:31.456 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.456 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.456
2025-07-02 04:52:31.456 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.456 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.456 alo = 48, ahi = 1101
2025-07-02 04:52:31.456 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.456 blo = 48, bhi = 1101
2025-07-02 04:52:31.456
2025-07-02 04:52:31.456 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.456 g = []
2025-07-02 04:52:31.456 if alo < ahi:
2025-07-02 04:52:31.456 if blo < bhi:
2025-07-02 04:52:31.456 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.456 else:
2025-07-02 04:52:31.456 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.456 elif blo < bhi:
2025-07-02 04:52:31.456 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.456
2025-07-02 04:52:31.456 > yield from g
2025-07-02 04:52:31.457
2025-07-02 04:52:31.457 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.457 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.457
2025-07-02 04:52:31.457 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.457 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.457 alo = 48, ahi = 1101
2025-07-02 04:52:31.457 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.457 blo = 48, bhi = 1101
2025-07-02 04:52:31.457
2025-07-02 04:52:31.457 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.457 r"""
2025-07-02 04:52:31.457 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.457 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.457 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.457 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.457
2025-07-02 04:52:31.457 Example:
2025-07-02 04:52:31.458
2025-07-02 04:52:31.458 >>> d = Differ()
2025-07-02 04:52:31.458 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.458 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.458 >>> print(''.join(results), end="")
2025-07-02 04:52:31.458 - abcDefghiJkl
2025-07-02 04:52:31.458 + abcdefGhijkl
2025-07-02 04:52:31.458 """
2025-07-02 04:52:31.458
2025-07-02 04:52:31.458 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.458 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.458 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.458 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.458 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.458
2025-07-02 04:52:31.458 # search for the pair that matches best without being identical
2025-07-02 04:52:31.458 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.458 # on junk -- unless we have to)
2025-07-02 04:52:31.458 for j in range(blo, bhi):
2025-07-02 04:52:31.459 bj = b[j]
2025-07-02 04:52:31.459 cruncher.set_seq2(bj)
2025-07-02 04:52:31.459 for i in range(alo, ahi):
2025-07-02 04:52:31.459 ai = a[i]
2025-07-02 04:52:31.459 if ai == bj:
2025-07-02 04:52:31.459 if eqi is None:
2025-07-02 04:52:31.459 eqi, eqj = i, j
2025-07-02 04:52:31.459 continue
2025-07-02 04:52:31.459 cruncher.set_seq1(ai)
2025-07-02 04:52:31.459 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.459 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.459 # compares by a factor of 3.
2025-07-02 04:52:31.459 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.459 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.459 # of the computation is cached by cruncher
2025-07-02 04:52:31.459 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.459 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.459 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.459 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.459 if best_ratio < cutoff:
2025-07-02 04:52:31.459 # no non-identical "pretty close" pair
2025-07-02 04:52:31.460 if eqi is None:
2025-07-02 04:52:31.460 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.460 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.460 return
2025-07-02 04:52:31.460 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.460 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.460 else:
2025-07-02 04:52:31.460 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.460 eqi = None
2025-07-02 04:52:31.460
2025-07-02 04:52:31.460 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.460 # identical
2025-07-02 04:52:31.460
2025-07-02 04:52:31.460 # pump out diffs from before the synch point
2025-07-02 04:52:31.460 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.460
2025-07-02 04:52:31.460 # do intraline marking on the synch pair
2025-07-02 04:52:31.460 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.460 if eqi is None:
2025-07-02 04:52:31.460 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.461 atags = btags = ""
2025-07-02 04:52:31.461 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.461 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.461 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.461 if tag == 'replace':
2025-07-02 04:52:31.461 atags += '^' * la
2025-07-02 04:52:31.461 btags += '^' * lb
2025-07-02 04:52:31.461 elif tag == 'delete':
2025-07-02 04:52:31.461 atags += '-' * la
2025-07-02 04:52:31.461 elif tag == 'insert':
2025-07-02 04:52:31.461 btags += '+' * lb
2025-07-02 04:52:31.461 elif tag == 'equal':
2025-07-02 04:52:31.461 atags += ' ' * la
2025-07-02 04:52:31.461 btags += ' ' * lb
2025-07-02 04:52:31.461 else:
2025-07-02 04:52:31.461 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.461 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.461 else:
2025-07-02 04:52:31.461 # the synch pair is identical
2025-07-02 04:52:31.461 yield ' ' + aelt
2025-07-02 04:52:31.461
2025-07-02 04:52:31.462 # pump out diffs from after the synch point
2025-07-02 04:52:31.462 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.462
2025-07-02 04:52:31.462 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.462 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.462
2025-07-02 04:52:31.462 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.462 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.462 alo = 49, ahi = 1101
2025-07-02 04:52:31.462 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.462 blo = 49, bhi = 1101
2025-07-02 04:52:31.462
2025-07-02 04:52:31.462 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.462 g = []
2025-07-02 04:52:31.462 if alo < ahi:
2025-07-02 04:52:31.462 if blo < bhi:
2025-07-02 04:52:31.462 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.462 else:
2025-07-02 04:52:31.462 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.462 elif blo < bhi:
2025-07-02 04:52:31.463 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.463
2025-07-02 04:52:31.463 > yield from g
2025-07-02 04:52:31.463
2025-07-02 04:52:31.463 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.463 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.463
2025-07-02 04:52:31.463 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.463 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.463 alo = 49, ahi = 1101
2025-07-02 04:52:31.463 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.463 blo = 49, bhi = 1101
2025-07-02 04:52:31.463
2025-07-02 04:52:31.463 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.463 r"""
2025-07-02 04:52:31.463 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.463 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.463 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.463 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.463
2025-07-02 04:52:31.463 Example:
2025-07-02 04:52:31.464
2025-07-02 04:52:31.464 >>> d = Differ()
2025-07-02 04:52:31.464 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.464 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.464 >>> print(''.join(results), end="")
2025-07-02 04:52:31.464 - abcDefghiJkl
2025-07-02 04:52:31.464 + abcdefGhijkl
2025-07-02 04:52:31.464 """
2025-07-02 04:52:31.464
2025-07-02 04:52:31.464 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.464 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.464 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.464 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.464 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.464
2025-07-02 04:52:31.464 # search for the pair that matches best without being identical
2025-07-02 04:52:31.464 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.464 # on junk -- unless we have to)
2025-07-02 04:52:31.465 for j in range(blo, bhi):
2025-07-02 04:52:31.465 bj = b[j]
2025-07-02 04:52:31.465 cruncher.set_seq2(bj)
2025-07-02 04:52:31.465 for i in range(alo, ahi):
2025-07-02 04:52:31.465 ai = a[i]
2025-07-02 04:52:31.465 if ai == bj:
2025-07-02 04:52:31.465 if eqi is None:
2025-07-02 04:52:31.465 eqi, eqj = i, j
2025-07-02 04:52:31.465 continue
2025-07-02 04:52:31.465 cruncher.set_seq1(ai)
2025-07-02 04:52:31.465 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.465 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.465 # compares by a factor of 3.
2025-07-02 04:52:31.465 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.465 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.465 # of the computation is cached by cruncher
2025-07-02 04:52:31.465 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.465 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.465 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.465 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.465 if best_ratio < cutoff:
2025-07-02 04:52:31.466 # no non-identical "pretty close" pair
2025-07-02 04:52:31.466 if eqi is None:
2025-07-02 04:52:31.466 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.466 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.466 return
2025-07-02 04:52:31.466 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.466 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.466 else:
2025-07-02 04:52:31.466 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.466 eqi = None
2025-07-02 04:52:31.466
2025-07-02 04:52:31.466 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.466 # identical
2025-07-02 04:52:31.466
2025-07-02 04:52:31.466 # pump out diffs from before the synch point
2025-07-02 04:52:31.466 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.466
2025-07-02 04:52:31.466 # do intraline marking on the synch pair
2025-07-02 04:52:31.466 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.466 if eqi is None:
2025-07-02 04:52:31.467 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.467 atags = btags = ""
2025-07-02 04:52:31.467 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.467 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.467 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.467 if tag == 'replace':
2025-07-02 04:52:31.467 atags += '^' * la
2025-07-02 04:52:31.467 btags += '^' * lb
2025-07-02 04:52:31.467 elif tag == 'delete':
2025-07-02 04:52:31.467 atags += '-' * la
2025-07-02 04:52:31.467 elif tag == 'insert':
2025-07-02 04:52:31.467 btags += '+' * lb
2025-07-02 04:52:31.467 elif tag == 'equal':
2025-07-02 04:52:31.467 atags += ' ' * la
2025-07-02 04:52:31.467 btags += ' ' * lb
2025-07-02 04:52:31.467 else:
2025-07-02 04:52:31.467 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.467 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.467 else:
2025-07-02 04:52:31.467 # the synch pair is identical
2025-07-02 04:52:31.467 yield ' ' + aelt
2025-07-02 04:52:31.468
2025-07-02 04:52:31.468 # pump out diffs from after the synch point
2025-07-02 04:52:31.468 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.468
2025-07-02 04:52:31.468 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.468 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.468
2025-07-02 04:52:31.468 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.468 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.468 alo = 50, ahi = 1101
2025-07-02 04:52:31.468 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.468 blo = 50, bhi = 1101
2025-07-02 04:52:31.468
2025-07-02 04:52:31.468 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.468 g = []
2025-07-02 04:52:31.468 if alo < ahi:
2025-07-02 04:52:31.468 if blo < bhi:
2025-07-02 04:52:31.468 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.468 else:
2025-07-02 04:52:31.468 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.468 elif blo < bhi:
2025-07-02 04:52:31.469 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.469
2025-07-02 04:52:31.469 > yield from g
2025-07-02 04:52:31.469
2025-07-02 04:52:31.469 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.469 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.469
2025-07-02 04:52:31.469 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.469 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.469 alo = 50, ahi = 1101
2025-07-02 04:52:31.469 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.469 blo = 50, bhi = 1101
2025-07-02 04:52:31.469
2025-07-02 04:52:31.469 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.469 r"""
2025-07-02 04:52:31.469 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.469 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.469 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.469 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.469
2025-07-02 04:52:31.470 Example:
2025-07-02 04:52:31.470
2025-07-02 04:52:31.470 >>> d = Differ()
2025-07-02 04:52:31.470 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.470 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.470 >>> print(''.join(results), end="")
2025-07-02 04:52:31.470 - abcDefghiJkl
2025-07-02 04:52:31.470 + abcdefGhijkl
2025-07-02 04:52:31.470 """
2025-07-02 04:52:31.470
2025-07-02 04:52:31.470 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.470 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.470 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.470 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.470 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.470
2025-07-02 04:52:31.470 # search for the pair that matches best without being identical
2025-07-02 04:52:31.470 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.471 # on junk -- unless we have to)
2025-07-02 04:52:31.471 for j in range(blo, bhi):
2025-07-02 04:52:31.471 bj = b[j]
2025-07-02 04:52:31.471 cruncher.set_seq2(bj)
2025-07-02 04:52:31.471 for i in range(alo, ahi):
2025-07-02 04:52:31.471 ai = a[i]
2025-07-02 04:52:31.471 if ai == bj:
2025-07-02 04:52:31.471 if eqi is None:
2025-07-02 04:52:31.471 eqi, eqj = i, j
2025-07-02 04:52:31.471 continue
2025-07-02 04:52:31.471 cruncher.set_seq1(ai)
2025-07-02 04:52:31.471 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.471 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.471 # compares by a factor of 3.
2025-07-02 04:52:31.471 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.471 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.471 # of the computation is cached by cruncher
2025-07-02 04:52:31.471 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.471 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.471 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.471 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.472 if best_ratio < cutoff:
2025-07-02 04:52:31.472 # no non-identical "pretty close" pair
2025-07-02 04:52:31.472 if eqi is None:
2025-07-02 04:52:31.472 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.472 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.472 return
2025-07-02 04:52:31.472 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.472 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.472 else:
2025-07-02 04:52:31.472 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.472 eqi = None
2025-07-02 04:52:31.472
2025-07-02 04:52:31.472 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.472 # identical
2025-07-02 04:52:31.472
2025-07-02 04:52:31.472 # pump out diffs from before the synch point
2025-07-02 04:52:31.472 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.472
2025-07-02 04:52:31.472 # do intraline marking on the synch pair
2025-07-02 04:52:31.472 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.473 if eqi is None:
2025-07-02 04:52:31.473 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.473 atags = btags = ""
2025-07-02 04:52:31.473 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.473 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.473 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.473 if tag == 'replace':
2025-07-02 04:52:31.473 atags += '^' * la
2025-07-02 04:52:31.473 btags += '^' * lb
2025-07-02 04:52:31.473 elif tag == 'delete':
2025-07-02 04:52:31.473 atags += '-' * la
2025-07-02 04:52:31.473 elif tag == 'insert':
2025-07-02 04:52:31.473 btags += '+' * lb
2025-07-02 04:52:31.473 elif tag == 'equal':
2025-07-02 04:52:31.473 atags += ' ' * la
2025-07-02 04:52:31.473 btags += ' ' * lb
2025-07-02 04:52:31.473 else:
2025-07-02 04:52:31.473 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.473 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.473 else:
2025-07-02 04:52:31.473 # the synch pair is identical
2025-07-02 04:52:31.474 yield ' ' + aelt
2025-07-02 04:52:31.474
2025-07-02 04:52:31.474 # pump out diffs from after the synch point
2025-07-02 04:52:31.474 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.474
2025-07-02 04:52:31.474 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.474 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.474
2025-07-02 04:52:31.474 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.474 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.474 alo = 51, ahi = 1101
2025-07-02 04:52:31.474 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.474 blo = 51, bhi = 1101
2025-07-02 04:52:31.474
2025-07-02 04:52:31.474 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.474 g = []
2025-07-02 04:52:31.474 if alo < ahi:
2025-07-02 04:52:31.474 if blo < bhi:
2025-07-02 04:52:31.474 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.474 else:
2025-07-02 04:52:31.475 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.475 elif blo < bhi:
2025-07-02 04:52:31.475 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.475
2025-07-02 04:52:31.475 > yield from g
2025-07-02 04:52:31.475
2025-07-02 04:52:31.475 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.475 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.475
2025-07-02 04:52:31.475 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.475 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.475 alo = 51, ahi = 1101
2025-07-02 04:52:31.475 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.475 blo = 51, bhi = 1101
2025-07-02 04:52:31.475
2025-07-02 04:52:31.475 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.475 r"""
2025-07-02 04:52:31.475 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.475 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.475 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.476 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.476
2025-07-02 04:52:31.476 Example:
2025-07-02 04:52:31.476
2025-07-02 04:52:31.476 >>> d = Differ()
2025-07-02 04:52:31.476 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.476 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.476 >>> print(''.join(results), end="")
2025-07-02 04:52:31.476 - abcDefghiJkl
2025-07-02 04:52:31.476 + abcdefGhijkl
2025-07-02 04:52:31.476 """
2025-07-02 04:52:31.476
2025-07-02 04:52:31.476 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.476 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.476 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.476 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.476 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.476
2025-07-02 04:52:31.476 # search for the pair that matches best without being identical
2025-07-02 04:52:31.477 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.477 # on junk -- unless we have to)
2025-07-02 04:52:31.477 for j in range(blo, bhi):
2025-07-02 04:52:31.477 bj = b[j]
2025-07-02 04:52:31.477 cruncher.set_seq2(bj)
2025-07-02 04:52:31.477 for i in range(alo, ahi):
2025-07-02 04:52:31.477 ai = a[i]
2025-07-02 04:52:31.477 if ai == bj:
2025-07-02 04:52:31.477 if eqi is None:
2025-07-02 04:52:31.477 eqi, eqj = i, j
2025-07-02 04:52:31.477 continue
2025-07-02 04:52:31.477 cruncher.set_seq1(ai)
2025-07-02 04:52:31.477 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.477 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.477 # compares by a factor of 3.
2025-07-02 04:52:31.477 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.477 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.477 # of the computation is cached by cruncher
2025-07-02 04:52:31.477 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.477 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.477 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.478 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.478 if best_ratio < cutoff:
2025-07-02 04:52:31.478 # no non-identical "pretty close" pair
2025-07-02 04:52:31.478 if eqi is None:
2025-07-02 04:52:31.478 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.478 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.478 return
2025-07-02 04:52:31.478 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.478 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.478 else:
2025-07-02 04:52:31.478 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.478 eqi = None
2025-07-02 04:52:31.478
2025-07-02 04:52:31.478 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.478 # identical
2025-07-02 04:52:31.478
2025-07-02 04:52:31.478 # pump out diffs from before the synch point
2025-07-02 04:52:31.478 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.478
2025-07-02 04:52:31.478 # do intraline marking on the synch pair
2025-07-02 04:52:31.479 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.479 if eqi is None:
2025-07-02 04:52:31.479 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.479 atags = btags = ""
2025-07-02 04:52:31.479 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.479 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.479 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.479 if tag == 'replace':
2025-07-02 04:52:31.479 atags += '^' * la
2025-07-02 04:52:31.479 btags += '^' * lb
2025-07-02 04:52:31.479 elif tag == 'delete':
2025-07-02 04:52:31.479 atags += '-' * la
2025-07-02 04:52:31.479 elif tag == 'insert':
2025-07-02 04:52:31.479 btags += '+' * lb
2025-07-02 04:52:31.479 elif tag == 'equal':
2025-07-02 04:52:31.479 atags += ' ' * la
2025-07-02 04:52:31.479 btags += ' ' * lb
2025-07-02 04:52:31.479 else:
2025-07-02 04:52:31.479 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.479 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.479 else:
2025-07-02 04:52:31.480 # the synch pair is identical
2025-07-02 04:52:31.480 yield ' ' + aelt
2025-07-02 04:52:31.480
2025-07-02 04:52:31.480 # pump out diffs from after the synch point
2025-07-02 04:52:31.480 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.480
2025-07-02 04:52:31.480 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.480 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.480
2025-07-02 04:52:31.480 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.480 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.480 alo = 52, ahi = 1101
2025-07-02 04:52:31.480 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.480 blo = 52, bhi = 1101
2025-07-02 04:52:31.480
2025-07-02 04:52:31.480 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.480 g = []
2025-07-02 04:52:31.480 if alo < ahi:
2025-07-02 04:52:31.480 if blo < bhi:
2025-07-02 04:52:31.480 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.481 else:
2025-07-02 04:52:31.481 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.481 elif blo < bhi:
2025-07-02 04:52:31.481 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.481
2025-07-02 04:52:31.481 > yield from g
2025-07-02 04:52:31.481
2025-07-02 04:52:31.481 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.481 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.481
2025-07-02 04:52:31.481 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.481 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.481 alo = 52, ahi = 1101
2025-07-02 04:52:31.481 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.481 blo = 52, bhi = 1101
2025-07-02 04:52:31.481
2025-07-02 04:52:31.481 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.481 r"""
2025-07-02 04:52:31.481 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.481 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.481 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.482 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.482
2025-07-02 04:52:31.482 Example:
2025-07-02 04:52:31.482
2025-07-02 04:52:31.482 >>> d = Differ()
2025-07-02 04:52:31.482 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.482 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.482 >>> print(''.join(results), end="")
2025-07-02 04:52:31.482 - abcDefghiJkl
2025-07-02 04:52:31.482 + abcdefGhijkl
2025-07-02 04:52:31.482 """
2025-07-02 04:52:31.482
2025-07-02 04:52:31.482 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.482 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.482 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.482 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.482 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.482
2025-07-02 04:52:31.483 # search for the pair that matches best without being identical
2025-07-02 04:52:31.483 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.483 # on junk -- unless we have to)
2025-07-02 04:52:31.483 for j in range(blo, bhi):
2025-07-02 04:52:31.483 bj = b[j]
2025-07-02 04:52:31.483 cruncher.set_seq2(bj)
2025-07-02 04:52:31.483 for i in range(alo, ahi):
2025-07-02 04:52:31.483 ai = a[i]
2025-07-02 04:52:31.483 if ai == bj:
2025-07-02 04:52:31.483 if eqi is None:
2025-07-02 04:52:31.483 eqi, eqj = i, j
2025-07-02 04:52:31.483 continue
2025-07-02 04:52:31.483 cruncher.set_seq1(ai)
2025-07-02 04:52:31.483 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.483 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.483 # compares by a factor of 3.
2025-07-02 04:52:31.483 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.483 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.483 # of the computation is cached by cruncher
2025-07-02 04:52:31.483 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.484 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.484 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.484 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.484 if best_ratio < cutoff:
2025-07-02 04:52:31.484 # no non-identical "pretty close" pair
2025-07-02 04:52:31.484 if eqi is None:
2025-07-02 04:52:31.484 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.484 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.484 return
2025-07-02 04:52:31.484 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.484 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.484 else:
2025-07-02 04:52:31.484 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.484 eqi = None
2025-07-02 04:52:31.484
2025-07-02 04:52:31.484 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.484 # identical
2025-07-02 04:52:31.484
2025-07-02 04:52:31.484 # pump out diffs from before the synch point
2025-07-02 04:52:31.484 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.484
2025-07-02 04:52:31.485 # do intraline marking on the synch pair
2025-07-02 04:52:31.485 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.485 if eqi is None:
2025-07-02 04:52:31.485 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.485 atags = btags = ""
2025-07-02 04:52:31.485 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.485 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.485 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.485 if tag == 'replace':
2025-07-02 04:52:31.485 atags += '^' * la
2025-07-02 04:52:31.485 btags += '^' * lb
2025-07-02 04:52:31.485 elif tag == 'delete':
2025-07-02 04:52:31.485 atags += '-' * la
2025-07-02 04:52:31.485 elif tag == 'insert':
2025-07-02 04:52:31.485 btags += '+' * lb
2025-07-02 04:52:31.485 elif tag == 'equal':
2025-07-02 04:52:31.485 atags += ' ' * la
2025-07-02 04:52:31.485 btags += ' ' * lb
2025-07-02 04:52:31.485 else:
2025-07-02 04:52:31.485 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.485 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.486 else:
2025-07-02 04:52:31.486 # the synch pair is identical
2025-07-02 04:52:31.486 yield ' ' + aelt
2025-07-02 04:52:31.486
2025-07-02 04:52:31.486 # pump out diffs from after the synch point
2025-07-02 04:52:31.486 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.486
2025-07-02 04:52:31.486 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.486 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.486
2025-07-02 04:52:31.486 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.486 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.486 alo = 53, ahi = 1101
2025-07-02 04:52:31.486 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.486 blo = 53, bhi = 1101
2025-07-02 04:52:31.486
2025-07-02 04:52:31.486 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.486 g = []
2025-07-02 04:52:31.487 if alo < ahi:
2025-07-02 04:52:31.487 if blo < bhi:
2025-07-02 04:52:31.487 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.487 else:
2025-07-02 04:52:31.487 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.487 elif blo < bhi:
2025-07-02 04:52:31.487 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.487
2025-07-02 04:52:31.487 > yield from g
2025-07-02 04:52:31.487
2025-07-02 04:52:31.487 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.487 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.487
2025-07-02 04:52:31.487 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.487 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.487 alo = 53, ahi = 1101
2025-07-02 04:52:31.487 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.487 blo = 53, bhi = 1101
2025-07-02 04:52:31.487
2025-07-02 04:52:31.487 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.487 r"""
2025-07-02 04:52:31.488 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.488 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.488 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.488 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.488
2025-07-02 04:52:31.488 Example:
2025-07-02 04:52:31.488
2025-07-02 04:52:31.488 >>> d = Differ()
2025-07-02 04:52:31.488 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.488 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.488 >>> print(''.join(results), end="")
2025-07-02 04:52:31.488 - abcDefghiJkl
2025-07-02 04:52:31.488 + abcdefGhijkl
2025-07-02 04:52:31.488 """
2025-07-02 04:52:31.488
2025-07-02 04:52:31.488 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.488 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.488 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.489 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.489 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.489
2025-07-02 04:52:31.489 # search for the pair that matches best without being identical
2025-07-02 04:52:31.489 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.489 # on junk -- unless we have to)
2025-07-02 04:52:31.489 for j in range(blo, bhi):
2025-07-02 04:52:31.489 bj = b[j]
2025-07-02 04:52:31.489 cruncher.set_seq2(bj)
2025-07-02 04:52:31.489 for i in range(alo, ahi):
2025-07-02 04:52:31.489 ai = a[i]
2025-07-02 04:52:31.489 if ai == bj:
2025-07-02 04:52:31.489 if eqi is None:
2025-07-02 04:52:31.489 eqi, eqj = i, j
2025-07-02 04:52:31.489 continue
2025-07-02 04:52:31.489 cruncher.set_seq1(ai)
2025-07-02 04:52:31.489 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.489 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.489 # compares by a factor of 3.
2025-07-02 04:52:31.489 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.489 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.490 # of the computation is cached by cruncher
2025-07-02 04:52:31.490 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.490 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.490 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.490 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.490 if best_ratio < cutoff:
2025-07-02 04:52:31.490 # no non-identical "pretty close" pair
2025-07-02 04:52:31.490 if eqi is None:
2025-07-02 04:52:31.490 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.490 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.490 return
2025-07-02 04:52:31.490 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.490 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.490 else:
2025-07-02 04:52:31.490 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.490 eqi = None
2025-07-02 04:52:31.490
2025-07-02 04:52:31.490 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.490 # identical
2025-07-02 04:52:31.491
2025-07-02 04:52:31.491 # pump out diffs from before the synch point
2025-07-02 04:52:31.491 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.491
2025-07-02 04:52:31.491 # do intraline marking on the synch pair
2025-07-02 04:52:31.491 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.491 if eqi is None:
2025-07-02 04:52:31.491 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.491 atags = btags = ""
2025-07-02 04:52:31.491 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.491 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.491 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.491 if tag == 'replace':
2025-07-02 04:52:31.491 atags += '^' * la
2025-07-02 04:52:31.491 btags += '^' * lb
2025-07-02 04:52:31.491 elif tag == 'delete':
2025-07-02 04:52:31.491 atags += '-' * la
2025-07-02 04:52:31.491 elif tag == 'insert':
2025-07-02 04:52:31.491 btags += '+' * lb
2025-07-02 04:52:31.491 elif tag == 'equal':
2025-07-02 04:52:31.492 atags += ' ' * la
2025-07-02 04:52:31.492 btags += ' ' * lb
2025-07-02 04:52:31.492 else:
2025-07-02 04:52:31.492 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.492 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.492 else:
2025-07-02 04:52:31.492 # the synch pair is identical
2025-07-02 04:52:31.492 yield ' ' + aelt
2025-07-02 04:52:31.492
2025-07-02 04:52:31.492 # pump out diffs from after the synch point
2025-07-02 04:52:31.492 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.492
2025-07-02 04:52:31.492 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.492 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.492
2025-07-02 04:52:31.492 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.492 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.492 alo = 54, ahi = 1101
2025-07-02 04:52:31.492 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.492 blo = 54, bhi = 1101
2025-07-02 04:52:31.493
2025-07-02 04:52:31.493 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.493 g = []
2025-07-02 04:52:31.493 if alo < ahi:
2025-07-02 04:52:31.493 if blo < bhi:
2025-07-02 04:52:31.493 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.493 else:
2025-07-02 04:52:31.493 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.493 elif blo < bhi:
2025-07-02 04:52:31.493 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.493
2025-07-02 04:52:31.493 > yield from g
2025-07-02 04:52:31.493
2025-07-02 04:52:31.493 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.493 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.493
2025-07-02 04:52:31.493 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.493 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.493 alo = 54, ahi = 1101
2025-07-02 04:52:31.493 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.493 blo = 54, bhi = 1101
2025-07-02 04:52:31.494
2025-07-02 04:52:31.494 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.494 r"""
2025-07-02 04:52:31.494 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.494 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.494 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.494 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.494
2025-07-02 04:52:31.494 Example:
2025-07-02 04:52:31.494
2025-07-02 04:52:31.494 >>> d = Differ()
2025-07-02 04:52:31.494 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.494 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.494 >>> print(''.join(results), end="")
2025-07-02 04:52:31.494 - abcDefghiJkl
2025-07-02 04:52:31.494 + abcdefGhijkl
2025-07-02 04:52:31.494 """
2025-07-02 04:52:31.494
2025-07-02 04:52:31.494 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.495 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.495 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.495 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.495 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.495
2025-07-02 04:52:31.495 # search for the pair that matches best without being identical
2025-07-02 04:52:31.495 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.495 # on junk -- unless we have to)
2025-07-02 04:52:31.495 for j in range(blo, bhi):
2025-07-02 04:52:31.495 bj = b[j]
2025-07-02 04:52:31.495 cruncher.set_seq2(bj)
2025-07-02 04:52:31.495 for i in range(alo, ahi):
2025-07-02 04:52:31.495 ai = a[i]
2025-07-02 04:52:31.495 if ai == bj:
2025-07-02 04:52:31.495 if eqi is None:
2025-07-02 04:52:31.495 eqi, eqj = i, j
2025-07-02 04:52:31.495 continue
2025-07-02 04:52:31.495 cruncher.set_seq1(ai)
2025-07-02 04:52:31.495 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.495 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.495 # compares by a factor of 3.
2025-07-02 04:52:31.496 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.496 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.496 # of the computation is cached by cruncher
2025-07-02 04:52:31.496 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.496 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.496 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.496 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.496 if best_ratio < cutoff:
2025-07-02 04:52:31.496 # no non-identical "pretty close" pair
2025-07-02 04:52:31.496 if eqi is None:
2025-07-02 04:52:31.496 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.496 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.496 return
2025-07-02 04:52:31.496 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.496 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.496 else:
2025-07-02 04:52:31.496 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.496 eqi = None
2025-07-02 04:52:31.496
2025-07-02 04:52:31.496 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.497 # identical
2025-07-02 04:52:31.497
2025-07-02 04:52:31.497 # pump out diffs from before the synch point
2025-07-02 04:52:31.497 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.497
2025-07-02 04:52:31.497 # do intraline marking on the synch pair
2025-07-02 04:52:31.497 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.497 if eqi is None:
2025-07-02 04:52:31.497 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.497 atags = btags = ""
2025-07-02 04:52:31.497 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.497 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.497 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.497 if tag == 'replace':
2025-07-02 04:52:31.497 atags += '^' * la
2025-07-02 04:52:31.497 btags += '^' * lb
2025-07-02 04:52:31.497 elif tag == 'delete':
2025-07-02 04:52:31.497 atags += '-' * la
2025-07-02 04:52:31.497 elif tag == 'insert':
2025-07-02 04:52:31.497 btags += '+' * lb
2025-07-02 04:52:31.497 elif tag == 'equal':
2025-07-02 04:52:31.498 atags += ' ' * la
2025-07-02 04:52:31.498 btags += ' ' * lb
2025-07-02 04:52:31.498 else:
2025-07-02 04:52:31.498 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.498 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.498 else:
2025-07-02 04:52:31.498 # the synch pair is identical
2025-07-02 04:52:31.498 yield ' ' + aelt
2025-07-02 04:52:31.498
2025-07-02 04:52:31.498 # pump out diffs from after the synch point
2025-07-02 04:52:31.498 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.498
2025-07-02 04:52:31.498 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.498 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.498
2025-07-02 04:52:31.498 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.498 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.498 alo = 55, ahi = 1101
2025-07-02 04:52:31.498 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.498 blo = 55, bhi = 1101
2025-07-02 04:52:31.498
2025-07-02 04:52:31.499 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.499 g = []
2025-07-02 04:52:31.499 if alo < ahi:
2025-07-02 04:52:31.499 if blo < bhi:
2025-07-02 04:52:31.499 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.499 else:
2025-07-02 04:52:31.499 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.499 elif blo < bhi:
2025-07-02 04:52:31.499 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.499
2025-07-02 04:52:31.499 > yield from g
2025-07-02 04:52:31.499
2025-07-02 04:52:31.499 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.499 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.499
2025-07-02 04:52:31.499 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.499 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.499 alo = 55, ahi = 1101
2025-07-02 04:52:31.499 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.500 blo = 55, bhi = 1101
2025-07-02 04:52:31.500
2025-07-02 04:52:31.500 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.500 r"""
2025-07-02 04:52:31.500 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.500 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.500 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.500 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.500
2025-07-02 04:52:31.500 Example:
2025-07-02 04:52:31.500
2025-07-02 04:52:31.500 >>> d = Differ()
2025-07-02 04:52:31.500 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.500 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.500 >>> print(''.join(results), end="")
2025-07-02 04:52:31.500 - abcDefghiJkl
2025-07-02 04:52:31.500 + abcdefGhijkl
2025-07-02 04:52:31.500 """
2025-07-02 04:52:31.501
2025-07-02 04:52:31.501 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.501 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.501 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.501 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.501 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.501
2025-07-02 04:52:31.501 # search for the pair that matches best without being identical
2025-07-02 04:52:31.501 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.501 # on junk -- unless we have to)
2025-07-02 04:52:31.501 for j in range(blo, bhi):
2025-07-02 04:52:31.501 bj = b[j]
2025-07-02 04:52:31.501 cruncher.set_seq2(bj)
2025-07-02 04:52:31.501 for i in range(alo, ahi):
2025-07-02 04:52:31.501 ai = a[i]
2025-07-02 04:52:31.501 if ai == bj:
2025-07-02 04:52:31.501 if eqi is None:
2025-07-02 04:52:31.501 eqi, eqj = i, j
2025-07-02 04:52:31.501 continue
2025-07-02 04:52:31.501 cruncher.set_seq1(ai)
2025-07-02 04:52:31.502 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.502 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.502 # compares by a factor of 3.
2025-07-02 04:52:31.502 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.502 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.502 # of the computation is cached by cruncher
2025-07-02 04:52:31.502 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.502 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.502 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.502 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.502 if best_ratio < cutoff:
2025-07-02 04:52:31.502 # no non-identical "pretty close" pair
2025-07-02 04:52:31.502 if eqi is None:
2025-07-02 04:52:31.502 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.502 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.502 return
2025-07-02 04:52:31.502 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.502 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.502 else:
2025-07-02 04:52:31.503 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.503 eqi = None
2025-07-02 04:52:31.503
2025-07-02 04:52:31.503 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.503 # identical
2025-07-02 04:52:31.503
2025-07-02 04:52:31.503 # pump out diffs from before the synch point
2025-07-02 04:52:31.503 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.503
2025-07-02 04:52:31.503 # do intraline marking on the synch pair
2025-07-02 04:52:31.503 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.503 if eqi is None:
2025-07-02 04:52:31.503 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.503 atags = btags = ""
2025-07-02 04:52:31.503 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.503 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.503 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.503 if tag == 'replace':
2025-07-02 04:52:31.503 atags += '^' * la
2025-07-02 04:52:31.503 btags += '^' * lb
2025-07-02 04:52:31.503 elif tag == 'delete':
2025-07-02 04:52:31.504 atags += '-' * la
2025-07-02 04:52:31.504 elif tag == 'insert':
2025-07-02 04:52:31.504 btags += '+' * lb
2025-07-02 04:52:31.504 elif tag == 'equal':
2025-07-02 04:52:31.504 atags += ' ' * la
2025-07-02 04:52:31.504 btags += ' ' * lb
2025-07-02 04:52:31.504 else:
2025-07-02 04:52:31.504 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.504 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.504 else:
2025-07-02 04:52:31.504 # the synch pair is identical
2025-07-02 04:52:31.504 yield ' ' + aelt
2025-07-02 04:52:31.504
2025-07-02 04:52:31.504 # pump out diffs from after the synch point
2025-07-02 04:52:31.504 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.504
2025-07-02 04:52:31.504 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.504 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.504
2025-07-02 04:52:31.504 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.504 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.505 alo = 56, ahi = 1101
2025-07-02 04:52:31.505 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.505 blo = 56, bhi = 1101
2025-07-02 04:52:31.505
2025-07-02 04:52:31.505 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.505 g = []
2025-07-02 04:52:31.505 if alo < ahi:
2025-07-02 04:52:31.505 if blo < bhi:
2025-07-02 04:52:31.505 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.505 else:
2025-07-02 04:52:31.505 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.505 elif blo < bhi:
2025-07-02 04:52:31.505 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.505
2025-07-02 04:52:31.505 > yield from g
2025-07-02 04:52:31.505
2025-07-02 04:52:31.505 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.505 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.505
2025-07-02 04:52:31.505 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.505 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.506 alo = 56, ahi = 1101
2025-07-02 04:52:31.506 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.506 blo = 56, bhi = 1101
2025-07-02 04:52:31.506
2025-07-02 04:52:31.506 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.506 r"""
2025-07-02 04:52:31.506 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.506 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.506 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.506 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.506
2025-07-02 04:52:31.506 Example:
2025-07-02 04:52:31.506
2025-07-02 04:52:31.506 >>> d = Differ()
2025-07-02 04:52:31.506 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.506 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.506 >>> print(''.join(results), end="")
2025-07-02 04:52:31.506 - abcDefghiJkl
2025-07-02 04:52:31.506 + abcdefGhijkl
2025-07-02 04:52:31.506 """
2025-07-02 04:52:31.507
2025-07-02 04:52:31.507 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.507 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.507 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.507 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.507 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.507
2025-07-02 04:52:31.507 # search for the pair that matches best without being identical
2025-07-02 04:52:31.507 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.507 # on junk -- unless we have to)
2025-07-02 04:52:31.507 for j in range(blo, bhi):
2025-07-02 04:52:31.507 bj = b[j]
2025-07-02 04:52:31.507 cruncher.set_seq2(bj)
2025-07-02 04:52:31.507 for i in range(alo, ahi):
2025-07-02 04:52:31.507 ai = a[i]
2025-07-02 04:52:31.507 if ai == bj:
2025-07-02 04:52:31.507 if eqi is None:
2025-07-02 04:52:31.507 eqi, eqj = i, j
2025-07-02 04:52:31.507 continue
2025-07-02 04:52:31.507 cruncher.set_seq1(ai)
2025-07-02 04:52:31.508 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.508 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.508 # compares by a factor of 3.
2025-07-02 04:52:31.508 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.508 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.508 # of the computation is cached by cruncher
2025-07-02 04:52:31.508 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.508 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.508 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.508 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.508 if best_ratio < cutoff:
2025-07-02 04:52:31.508 # no non-identical "pretty close" pair
2025-07-02 04:52:31.508 if eqi is None:
2025-07-02 04:52:31.508 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.508 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.508 return
2025-07-02 04:52:31.508 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.508 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.508 else:
2025-07-02 04:52:31.508 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.509 eqi = None
2025-07-02 04:52:31.509
2025-07-02 04:52:31.509 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.509 # identical
2025-07-02 04:52:31.509
2025-07-02 04:52:31.509 # pump out diffs from before the synch point
2025-07-02 04:52:31.509 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.509
2025-07-02 04:52:31.509 # do intraline marking on the synch pair
2025-07-02 04:52:31.509 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.509 if eqi is None:
2025-07-02 04:52:31.509 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.509 atags = btags = ""
2025-07-02 04:52:31.509 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.509 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.509 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.509 if tag == 'replace':
2025-07-02 04:52:31.509 atags += '^' * la
2025-07-02 04:52:31.509 btags += '^' * lb
2025-07-02 04:52:31.509 elif tag == 'delete':
2025-07-02 04:52:31.509 atags += '-' * la
2025-07-02 04:52:31.510 elif tag == 'insert':
2025-07-02 04:52:31.510 btags += '+' * lb
2025-07-02 04:52:31.510 elif tag == 'equal':
2025-07-02 04:52:31.510 atags += ' ' * la
2025-07-02 04:52:31.510 btags += ' ' * lb
2025-07-02 04:52:31.510 else:
2025-07-02 04:52:31.510 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.510 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.510 else:
2025-07-02 04:52:31.510 # the synch pair is identical
2025-07-02 04:52:31.510 yield ' ' + aelt
2025-07-02 04:52:31.510
2025-07-02 04:52:31.510 # pump out diffs from after the synch point
2025-07-02 04:52:31.510 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.510
2025-07-02 04:52:31.510 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.510 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.510
2025-07-02 04:52:31.510 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.510 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.510 alo = 57, ahi = 1101
2025-07-02 04:52:31.511 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.511 blo = 57, bhi = 1101
2025-07-02 04:52:31.511
2025-07-02 04:52:31.511 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.511 g = []
2025-07-02 04:52:31.511 if alo < ahi:
2025-07-02 04:52:31.511 if blo < bhi:
2025-07-02 04:52:31.511 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.511 else:
2025-07-02 04:52:31.511 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.511 elif blo < bhi:
2025-07-02 04:52:31.511 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.511
2025-07-02 04:52:31.511 > yield from g
2025-07-02 04:52:31.511
2025-07-02 04:52:31.511 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.511 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.511
2025-07-02 04:52:31.511 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.511 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.511 alo = 57, ahi = 1101
2025-07-02 04:52:31.512 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.512 blo = 57, bhi = 1101
2025-07-02 04:52:31.512
2025-07-02 04:52:31.512 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.512 r"""
2025-07-02 04:52:31.512 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.512 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.512 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.512 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.512
2025-07-02 04:52:31.512 Example:
2025-07-02 04:52:31.512
2025-07-02 04:52:31.512 >>> d = Differ()
2025-07-02 04:52:31.512 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.512 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.512 >>> print(''.join(results), end="")
2025-07-02 04:52:31.512 - abcDefghiJkl
2025-07-02 04:52:31.512 + abcdefGhijkl
2025-07-02 04:52:31.512 """
2025-07-02 04:52:31.512
2025-07-02 04:52:31.513 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.513 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.513 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.513 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.513 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.513
2025-07-02 04:52:31.513 # search for the pair that matches best without being identical
2025-07-02 04:52:31.513 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.513 # on junk -- unless we have to)
2025-07-02 04:52:31.513 for j in range(blo, bhi):
2025-07-02 04:52:31.513 bj = b[j]
2025-07-02 04:52:31.513 cruncher.set_seq2(bj)
2025-07-02 04:52:31.513 for i in range(alo, ahi):
2025-07-02 04:52:31.513 ai = a[i]
2025-07-02 04:52:31.513 if ai == bj:
2025-07-02 04:52:31.513 if eqi is None:
2025-07-02 04:52:31.513 eqi, eqj = i, j
2025-07-02 04:52:31.513 continue
2025-07-02 04:52:31.513 cruncher.set_seq1(ai)
2025-07-02 04:52:31.513 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.513 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.514 # compares by a factor of 3.
2025-07-02 04:52:31.514 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.514 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.514 # of the computation is cached by cruncher
2025-07-02 04:52:31.514 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.514 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.514 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.514 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.514 if best_ratio < cutoff:
2025-07-02 04:52:31.514 # no non-identical "pretty close" pair
2025-07-02 04:52:31.514 if eqi is None:
2025-07-02 04:52:31.514 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.514 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.514 return
2025-07-02 04:52:31.514 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.514 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.514 else:
2025-07-02 04:52:31.514 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.514 eqi = None
2025-07-02 04:52:31.514
2025-07-02 04:52:31.514 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.514 # identical
2025-07-02 04:52:31.515
2025-07-02 04:52:31.515 # pump out diffs from before the synch point
2025-07-02 04:52:31.515 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.515
2025-07-02 04:52:31.515 # do intraline marking on the synch pair
2025-07-02 04:52:31.515 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.515 if eqi is None:
2025-07-02 04:52:31.515 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.515 atags = btags = ""
2025-07-02 04:52:31.515 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.515 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.515 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.515 if tag == 'replace':
2025-07-02 04:52:31.515 atags += '^' * la
2025-07-02 04:52:31.515 btags += '^' * lb
2025-07-02 04:52:31.515 elif tag == 'delete':
2025-07-02 04:52:31.515 atags += '-' * la
2025-07-02 04:52:31.515 elif tag == 'insert':
2025-07-02 04:52:31.515 btags += '+' * lb
2025-07-02 04:52:31.515 elif tag == 'equal':
2025-07-02 04:52:31.515 atags += ' ' * la
2025-07-02 04:52:31.516 btags += ' ' * lb
2025-07-02 04:52:31.516 else:
2025-07-02 04:52:31.516 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.516 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.516 else:
2025-07-02 04:52:31.516 # the synch pair is identical
2025-07-02 04:52:31.516 yield ' ' + aelt
2025-07-02 04:52:31.516
2025-07-02 04:52:31.516 # pump out diffs from after the synch point
2025-07-02 04:52:31.516 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.516
2025-07-02 04:52:31.516 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.516 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.516
2025-07-02 04:52:31.516 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.516 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.516 alo = 58, ahi = 1101
2025-07-02 04:52:31.516 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.516 blo = 58, bhi = 1101
2025-07-02 04:52:31.516
2025-07-02 04:52:31.517 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.517 g = []
2025-07-02 04:52:31.517 if alo < ahi:
2025-07-02 04:52:31.517 if blo < bhi:
2025-07-02 04:52:31.517 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.517 else:
2025-07-02 04:52:31.517 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.517 elif blo < bhi:
2025-07-02 04:52:31.517 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.517
2025-07-02 04:52:31.517 > yield from g
2025-07-02 04:52:31.517
2025-07-02 04:52:31.517 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.517 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.517
2025-07-02 04:52:31.517 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.517 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.517 alo = 58, ahi = 1101
2025-07-02 04:52:31.517 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.517 blo = 58, bhi = 1101
2025-07-02 04:52:31.518
2025-07-02 04:52:31.518 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.518 r"""
2025-07-02 04:52:31.518 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.518 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.518 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.518 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.518
2025-07-02 04:52:31.518 Example:
2025-07-02 04:52:31.518
2025-07-02 04:52:31.518 >>> d = Differ()
2025-07-02 04:52:31.518 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.518 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.518 >>> print(''.join(results), end="")
2025-07-02 04:52:31.518 - abcDefghiJkl
2025-07-02 04:52:31.518 + abcdefGhijkl
2025-07-02 04:52:31.518 """
2025-07-02 04:52:31.518
2025-07-02 04:52:31.519 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.519 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.519 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.519 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.519 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.519
2025-07-02 04:52:31.519 # search for the pair that matches best without being identical
2025-07-02 04:52:31.519 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.519 # on junk -- unless we have to)
2025-07-02 04:52:31.519 for j in range(blo, bhi):
2025-07-02 04:52:31.519 bj = b[j]
2025-07-02 04:52:31.519 cruncher.set_seq2(bj)
2025-07-02 04:52:31.519 for i in range(alo, ahi):
2025-07-02 04:52:31.519 ai = a[i]
2025-07-02 04:52:31.519 if ai == bj:
2025-07-02 04:52:31.519 if eqi is None:
2025-07-02 04:52:31.519 eqi, eqj = i, j
2025-07-02 04:52:31.519 continue
2025-07-02 04:52:31.519 cruncher.set_seq1(ai)
2025-07-02 04:52:31.519 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.519 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.520 # compares by a factor of 3.
2025-07-02 04:52:31.520 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.520 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.520 # of the computation is cached by cruncher
2025-07-02 04:52:31.520 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.520 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.520 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.520 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.520 if best_ratio < cutoff:
2025-07-02 04:52:31.520 # no non-identical "pretty close" pair
2025-07-02 04:52:31.520 if eqi is None:
2025-07-02 04:52:31.520 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.520 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.520 return
2025-07-02 04:52:31.520 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.520 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.520 else:
2025-07-02 04:52:31.520 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.520 eqi = None
2025-07-02 04:52:31.520
2025-07-02 04:52:31.520 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.520 # identical
2025-07-02 04:52:31.521
2025-07-02 04:52:31.521 # pump out diffs from before the synch point
2025-07-02 04:52:31.521 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.521
2025-07-02 04:52:31.521 # do intraline marking on the synch pair
2025-07-02 04:52:31.521 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.521 if eqi is None:
2025-07-02 04:52:31.521 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.521 atags = btags = ""
2025-07-02 04:52:31.521 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.521 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.521 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.521 if tag == 'replace':
2025-07-02 04:52:31.521 atags += '^' * la
2025-07-02 04:52:31.521 btags += '^' * lb
2025-07-02 04:52:31.521 elif tag == 'delete':
2025-07-02 04:52:31.521 atags += '-' * la
2025-07-02 04:52:31.521 elif tag == 'insert':
2025-07-02 04:52:31.521 btags += '+' * lb
2025-07-02 04:52:31.521 elif tag == 'equal':
2025-07-02 04:52:31.521 atags += ' ' * la
2025-07-02 04:52:31.522 btags += ' ' * lb
2025-07-02 04:52:31.522 else:
2025-07-02 04:52:31.522 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.522 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.522 else:
2025-07-02 04:52:31.522 # the synch pair is identical
2025-07-02 04:52:31.522 yield ' ' + aelt
2025-07-02 04:52:31.522
2025-07-02 04:52:31.522 # pump out diffs from after the synch point
2025-07-02 04:52:31.522 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.522
2025-07-02 04:52:31.522 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.522 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.522
2025-07-02 04:52:31.522 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.522 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.522 alo = 59, ahi = 1101
2025-07-02 04:52:31.522 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.522 blo = 59, bhi = 1101
2025-07-02 04:52:31.522
2025-07-02 04:52:31.522 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.523 g = []
2025-07-02 04:52:31.523 if alo < ahi:
2025-07-02 04:52:31.523 if blo < bhi:
2025-07-02 04:52:31.523 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.523 else:
2025-07-02 04:52:31.523 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.523 elif blo < bhi:
2025-07-02 04:52:31.523 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.523
2025-07-02 04:52:31.523 > yield from g
2025-07-02 04:52:31.523
2025-07-02 04:52:31.523 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.523 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.523
2025-07-02 04:52:31.523 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.523 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.523 alo = 59, ahi = 1101
2025-07-02 04:52:31.523 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.523 blo = 59, bhi = 1101
2025-07-02 04:52:31.523
2025-07-02 04:52:31.523 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.524 r"""
2025-07-02 04:52:31.524 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.524 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.524 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.524 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.524
2025-07-02 04:52:31.524 Example:
2025-07-02 04:52:31.524
2025-07-02 04:52:31.524 >>> d = Differ()
2025-07-02 04:52:31.524 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.524 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.524 >>> print(''.join(results), end="")
2025-07-02 04:52:31.524 - abcDefghiJkl
2025-07-02 04:52:31.524 + abcdefGhijkl
2025-07-02 04:52:31.524 """
2025-07-02 04:52:31.524
2025-07-02 04:52:31.524 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.524 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.525 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.525 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.525 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.525
2025-07-02 04:52:31.525 # search for the pair that matches best without being identical
2025-07-02 04:52:31.525 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.525 # on junk -- unless we have to)
2025-07-02 04:52:31.525 for j in range(blo, bhi):
2025-07-02 04:52:31.525 bj = b[j]
2025-07-02 04:52:31.525 cruncher.set_seq2(bj)
2025-07-02 04:52:31.525 for i in range(alo, ahi):
2025-07-02 04:52:31.525 ai = a[i]
2025-07-02 04:52:31.525 if ai == bj:
2025-07-02 04:52:31.525 if eqi is None:
2025-07-02 04:52:31.525 eqi, eqj = i, j
2025-07-02 04:52:31.525 continue
2025-07-02 04:52:31.525 cruncher.set_seq1(ai)
2025-07-02 04:52:31.525 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.525 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.525 # compares by a factor of 3.
2025-07-02 04:52:31.525 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.526 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.526 # of the computation is cached by cruncher
2025-07-02 04:52:31.526 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.526 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.526 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.526 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.526 if best_ratio < cutoff:
2025-07-02 04:52:31.526 # no non-identical "pretty close" pair
2025-07-02 04:52:31.526 if eqi is None:
2025-07-02 04:52:31.526 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.526 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.526 return
2025-07-02 04:52:31.526 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.526 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.526 else:
2025-07-02 04:52:31.526 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.526 eqi = None
2025-07-02 04:52:31.526
2025-07-02 04:52:31.526 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.526 # identical
2025-07-02 04:52:31.526
2025-07-02 04:52:31.527 # pump out diffs from before the synch point
2025-07-02 04:52:31.527 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.527
2025-07-02 04:52:31.527 # do intraline marking on the synch pair
2025-07-02 04:52:31.527 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.527 if eqi is None:
2025-07-02 04:52:31.527 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.527 atags = btags = ""
2025-07-02 04:52:31.527 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.527 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.527 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.527 if tag == 'replace':
2025-07-02 04:52:31.527 atags += '^' * la
2025-07-02 04:52:31.527 btags += '^' * lb
2025-07-02 04:52:31.527 elif tag == 'delete':
2025-07-02 04:52:31.527 atags += '-' * la
2025-07-02 04:52:31.527 elif tag == 'insert':
2025-07-02 04:52:31.527 btags += '+' * lb
2025-07-02 04:52:31.527 elif tag == 'equal':
2025-07-02 04:52:31.527 atags += ' ' * la
2025-07-02 04:52:31.527 btags += ' ' * lb
2025-07-02 04:52:31.527 else:
2025-07-02 04:52:31.528 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.528 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.528 else:
2025-07-02 04:52:31.528 # the synch pair is identical
2025-07-02 04:52:31.528 yield ' ' + aelt
2025-07-02 04:52:31.528
2025-07-02 04:52:31.528 # pump out diffs from after the synch point
2025-07-02 04:52:31.528 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.528
2025-07-02 04:52:31.528 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.528 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.528
2025-07-02 04:52:31.528 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.528 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.528 alo = 60, ahi = 1101
2025-07-02 04:52:31.528 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.528 blo = 60, bhi = 1101
2025-07-02 04:52:31.528
2025-07-02 04:52:31.528 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.528 g = []
2025-07-02 04:52:31.528 if alo < ahi:
2025-07-02 04:52:31.529 if blo < bhi:
2025-07-02 04:52:31.529 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.529 else:
2025-07-02 04:52:31.529 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.529 elif blo < bhi:
2025-07-02 04:52:31.529 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.529
2025-07-02 04:52:31.529 > yield from g
2025-07-02 04:52:31.529
2025-07-02 04:52:31.529 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.529 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.529
2025-07-02 04:52:31.529 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.529 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.529 alo = 60, ahi = 1101
2025-07-02 04:52:31.529 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.529 blo = 60, bhi = 1101
2025-07-02 04:52:31.529
2025-07-02 04:52:31.529 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.529 r"""
2025-07-02 04:52:31.529 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.530 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.530 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.530 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.530
2025-07-02 04:52:31.530 Example:
2025-07-02 04:52:31.530
2025-07-02 04:52:31.530 >>> d = Differ()
2025-07-02 04:52:31.530 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.530 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.530 >>> print(''.join(results), end="")
2025-07-02 04:52:31.530 - abcDefghiJkl
2025-07-02 04:52:31.530 + abcdefGhijkl
2025-07-02 04:52:31.530 """
2025-07-02 04:52:31.530
2025-07-02 04:52:31.530 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.530 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.530 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.530 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.530 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.530
2025-07-02 04:52:31.531 # search for the pair that matches best without being identical
2025-07-02 04:52:31.531 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.531 # on junk -- unless we have to)
2025-07-02 04:52:31.531 for j in range(blo, bhi):
2025-07-02 04:52:31.531 bj = b[j]
2025-07-02 04:52:31.531 cruncher.set_seq2(bj)
2025-07-02 04:52:31.531 for i in range(alo, ahi):
2025-07-02 04:52:31.531 ai = a[i]
2025-07-02 04:52:31.531 if ai == bj:
2025-07-02 04:52:31.531 if eqi is None:
2025-07-02 04:52:31.531 eqi, eqj = i, j
2025-07-02 04:52:31.531 continue
2025-07-02 04:52:31.531 cruncher.set_seq1(ai)
2025-07-02 04:52:31.531 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.531 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.531 # compares by a factor of 3.
2025-07-02 04:52:31.531 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.531 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.531 # of the computation is cached by cruncher
2025-07-02 04:52:31.531 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.531 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.532 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.532 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.532 if best_ratio < cutoff:
2025-07-02 04:52:31.532 # no non-identical "pretty close" pair
2025-07-02 04:52:31.532 if eqi is None:
2025-07-02 04:52:31.532 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.532 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.532 return
2025-07-02 04:52:31.532 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.532 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.532 else:
2025-07-02 04:52:31.532 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.532 eqi = None
2025-07-02 04:52:31.532
2025-07-02 04:52:31.532 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.532 # identical
2025-07-02 04:52:31.532
2025-07-02 04:52:31.532 # pump out diffs from before the synch point
2025-07-02 04:52:31.532 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.532
2025-07-02 04:52:31.533 # do intraline marking on the synch pair
2025-07-02 04:52:31.533 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.533 if eqi is None:
2025-07-02 04:52:31.533 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.533 atags = btags = ""
2025-07-02 04:52:31.533 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.533 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.533 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.533 if tag == 'replace':
2025-07-02 04:52:31.533 atags += '^' * la
2025-07-02 04:52:31.533 btags += '^' * lb
2025-07-02 04:52:31.533 elif tag == 'delete':
2025-07-02 04:52:31.533 atags += '-' * la
2025-07-02 04:52:31.533 elif tag == 'insert':
2025-07-02 04:52:31.533 btags += '+' * lb
2025-07-02 04:52:31.533 elif tag == 'equal':
2025-07-02 04:52:31.533 atags += ' ' * la
2025-07-02 04:52:31.533 btags += ' ' * lb
2025-07-02 04:52:31.533 else:
2025-07-02 04:52:31.533 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.533 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.534 else:
2025-07-02 04:52:31.534 # the synch pair is identical
2025-07-02 04:52:31.534 yield ' ' + aelt
2025-07-02 04:52:31.534
2025-07-02 04:52:31.534 # pump out diffs from after the synch point
2025-07-02 04:52:31.534 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.534
2025-07-02 04:52:31.534 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.534 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.534
2025-07-02 04:52:31.534 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.534 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.534 alo = 61, ahi = 1101
2025-07-02 04:52:31.534 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.534 blo = 61, bhi = 1101
2025-07-02 04:52:31.534
2025-07-02 04:52:31.534 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.534 g = []
2025-07-02 04:52:31.534 if alo < ahi:
2025-07-02 04:52:31.534 if blo < bhi:
2025-07-02 04:52:31.535 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.535 else:
2025-07-02 04:52:31.535 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.535 elif blo < bhi:
2025-07-02 04:52:31.535 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.535
2025-07-02 04:52:31.535 > yield from g
2025-07-02 04:52:31.535
2025-07-02 04:52:31.535 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.535 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.535
2025-07-02 04:52:31.535 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.535 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.535 alo = 61, ahi = 1101
2025-07-02 04:52:31.535 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.535 blo = 61, bhi = 1101
2025-07-02 04:52:31.535
2025-07-02 04:52:31.535 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.535 r"""
2025-07-02 04:52:31.535 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.535 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.536 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.536 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.536
2025-07-02 04:52:31.536 Example:
2025-07-02 04:52:31.536
2025-07-02 04:52:31.536 >>> d = Differ()
2025-07-02 04:52:31.536 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.536 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.536 >>> print(''.join(results), end="")
2025-07-02 04:52:31.536 - abcDefghiJkl
2025-07-02 04:52:31.536 + abcdefGhijkl
2025-07-02 04:52:31.536 """
2025-07-02 04:52:31.536
2025-07-02 04:52:31.536 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.536 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.536 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.536 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.536 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.536
2025-07-02 04:52:31.537 # search for the pair that matches best without being identical
2025-07-02 04:52:31.537 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.537 # on junk -- unless we have to)
2025-07-02 04:52:31.537 for j in range(blo, bhi):
2025-07-02 04:52:31.537 bj = b[j]
2025-07-02 04:52:31.537 cruncher.set_seq2(bj)
2025-07-02 04:52:31.537 for i in range(alo, ahi):
2025-07-02 04:52:31.537 ai = a[i]
2025-07-02 04:52:31.537 if ai == bj:
2025-07-02 04:52:31.537 if eqi is None:
2025-07-02 04:52:31.537 eqi, eqj = i, j
2025-07-02 04:52:31.537 continue
2025-07-02 04:52:31.537 cruncher.set_seq1(ai)
2025-07-02 04:52:31.537 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.537 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.537 # compares by a factor of 3.
2025-07-02 04:52:31.537 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.537 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.537 # of the computation is cached by cruncher
2025-07-02 04:52:31.537 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.537 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.537 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.538 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.538 if best_ratio < cutoff:
2025-07-02 04:52:31.538 # no non-identical "pretty close" pair
2025-07-02 04:52:31.538 if eqi is None:
2025-07-02 04:52:31.538 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.538 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.538 return
2025-07-02 04:52:31.538 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.538 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.538 else:
2025-07-02 04:52:31.538 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.538 eqi = None
2025-07-02 04:52:31.538
2025-07-02 04:52:31.538 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.538 # identical
2025-07-02 04:52:31.538
2025-07-02 04:52:31.538 # pump out diffs from before the synch point
2025-07-02 04:52:31.538 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.538
2025-07-02 04:52:31.538 # do intraline marking on the synch pair
2025-07-02 04:52:31.538 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.539 if eqi is None:
2025-07-02 04:52:31.539 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.539 atags = btags = ""
2025-07-02 04:52:31.539 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.539 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.539 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.539 if tag == 'replace':
2025-07-02 04:52:31.539 atags += '^' * la
2025-07-02 04:52:31.539 btags += '^' * lb
2025-07-02 04:52:31.539 elif tag == 'delete':
2025-07-02 04:52:31.539 atags += '-' * la
2025-07-02 04:52:31.539 elif tag == 'insert':
2025-07-02 04:52:31.539 btags += '+' * lb
2025-07-02 04:52:31.539 elif tag == 'equal':
2025-07-02 04:52:31.539 atags += ' ' * la
2025-07-02 04:52:31.539 btags += ' ' * lb
2025-07-02 04:52:31.539 else:
2025-07-02 04:52:31.539 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.539 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.539 else:
2025-07-02 04:52:31.539 # the synch pair is identical
2025-07-02 04:52:31.539 yield ' ' + aelt
2025-07-02 04:52:31.540
2025-07-02 04:52:31.540 # pump out diffs from after the synch point
2025-07-02 04:52:31.540 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.540
2025-07-02 04:52:31.540 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.540 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.540
2025-07-02 04:52:31.540 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.540 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.540 alo = 62, ahi = 1101
2025-07-02 04:52:31.540 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.540 blo = 62, bhi = 1101
2025-07-02 04:52:31.540
2025-07-02 04:52:31.540 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.540 g = []
2025-07-02 04:52:31.540 if alo < ahi:
2025-07-02 04:52:31.540 if blo < bhi:
2025-07-02 04:52:31.540 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.540 else:
2025-07-02 04:52:31.541 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.541 elif blo < bhi:
2025-07-02 04:52:31.541 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.541
2025-07-02 04:52:31.541 > yield from g
2025-07-02 04:52:31.541
2025-07-02 04:52:31.541 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.541 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.541
2025-07-02 04:52:31.541 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.541 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.541 alo = 62, ahi = 1101
2025-07-02 04:52:31.541 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.541 blo = 62, bhi = 1101
2025-07-02 04:52:31.541
2025-07-02 04:52:31.541 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.541 r"""
2025-07-02 04:52:31.541 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.541 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.541 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.541 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.542
2025-07-02 04:52:31.542 Example:
2025-07-02 04:52:31.542
2025-07-02 04:52:31.542 >>> d = Differ()
2025-07-02 04:52:31.542 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.542 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.542 >>> print(''.join(results), end="")
2025-07-02 04:52:31.542 - abcDefghiJkl
2025-07-02 04:52:31.542 + abcdefGhijkl
2025-07-02 04:52:31.542 """
2025-07-02 04:52:31.542
2025-07-02 04:52:31.542 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.542 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.542 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.542 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.542 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.542
2025-07-02 04:52:31.543 # search for the pair that matches best without being identical
2025-07-02 04:52:31.543 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.543 # on junk -- unless we have to)
2025-07-02 04:52:31.543 for j in range(blo, bhi):
2025-07-02 04:52:31.543 bj = b[j]
2025-07-02 04:52:31.543 cruncher.set_seq2(bj)
2025-07-02 04:52:31.543 for i in range(alo, ahi):
2025-07-02 04:52:31.543 ai = a[i]
2025-07-02 04:52:31.543 if ai == bj:
2025-07-02 04:52:31.543 if eqi is None:
2025-07-02 04:52:31.543 eqi, eqj = i, j
2025-07-02 04:52:31.543 continue
2025-07-02 04:52:31.543 cruncher.set_seq1(ai)
2025-07-02 04:52:31.543 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.543 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.543 # compares by a factor of 3.
2025-07-02 04:52:31.543 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.543 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.543 # of the computation is cached by cruncher
2025-07-02 04:52:31.543 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.543 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.544 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.544 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.544 if best_ratio < cutoff:
2025-07-02 04:52:31.544 # no non-identical "pretty close" pair
2025-07-02 04:52:31.544 if eqi is None:
2025-07-02 04:52:31.544 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.544 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.544 return
2025-07-02 04:52:31.544 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.544 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.544 else:
2025-07-02 04:52:31.544 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.544 eqi = None
2025-07-02 04:52:31.544
2025-07-02 04:52:31.544 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.544 # identical
2025-07-02 04:52:31.544
2025-07-02 04:52:31.544 # pump out diffs from before the synch point
2025-07-02 04:52:31.544 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.544
2025-07-02 04:52:31.544 # do intraline marking on the synch pair
2025-07-02 04:52:31.544 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.545 if eqi is None:
2025-07-02 04:52:31.545 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.545 atags = btags = ""
2025-07-02 04:52:31.545 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.545 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.545 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.545 if tag == 'replace':
2025-07-02 04:52:31.545 atags += '^' * la
2025-07-02 04:52:31.545 btags += '^' * lb
2025-07-02 04:52:31.545 elif tag == 'delete':
2025-07-02 04:52:31.545 atags += '-' * la
2025-07-02 04:52:31.545 elif tag == 'insert':
2025-07-02 04:52:31.545 btags += '+' * lb
2025-07-02 04:52:31.545 elif tag == 'equal':
2025-07-02 04:52:31.545 atags += ' ' * la
2025-07-02 04:52:31.545 btags += ' ' * lb
2025-07-02 04:52:31.545 else:
2025-07-02 04:52:31.545 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.545 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.545 else:
2025-07-02 04:52:31.545 # the synch pair is identical
2025-07-02 04:52:31.546 yield ' ' + aelt
2025-07-02 04:52:31.546
2025-07-02 04:52:31.546 # pump out diffs from after the synch point
2025-07-02 04:52:31.546 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.546
2025-07-02 04:52:31.546 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.546 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.546
2025-07-02 04:52:31.546 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.546 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.546 alo = 63, ahi = 1101
2025-07-02 04:52:31.546 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.546 blo = 63, bhi = 1101
2025-07-02 04:52:31.546
2025-07-02 04:52:31.546 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.546 g = []
2025-07-02 04:52:31.546 if alo < ahi:
2025-07-02 04:52:31.546 if blo < bhi:
2025-07-02 04:52:31.546 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.546 else:
2025-07-02 04:52:31.546 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.547 elif blo < bhi:
2025-07-02 04:52:31.547 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.547
2025-07-02 04:52:31.547 > yield from g
2025-07-02 04:52:31.547
2025-07-02 04:52:31.547 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.547 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.547
2025-07-02 04:52:31.547 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.547 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.547 alo = 63, ahi = 1101
2025-07-02 04:52:31.547 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.547 blo = 63, bhi = 1101
2025-07-02 04:52:31.547
2025-07-02 04:52:31.547 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.547 r"""
2025-07-02 04:52:31.547 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.547 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.547 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.547 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.547
2025-07-02 04:52:31.547 Example:
2025-07-02 04:52:31.548
2025-07-02 04:52:31.548 >>> d = Differ()
2025-07-02 04:52:31.548 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.548 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.548 >>> print(''.join(results), end="")
2025-07-02 04:52:31.548 - abcDefghiJkl
2025-07-02 04:52:31.548 + abcdefGhijkl
2025-07-02 04:52:31.548 """
2025-07-02 04:52:31.548
2025-07-02 04:52:31.548 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.548 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.548 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.548 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.548 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.548
2025-07-02 04:52:31.548 # search for the pair that matches best without being identical
2025-07-02 04:52:31.548 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.548 # on junk -- unless we have to)
2025-07-02 04:52:31.549 for j in range(blo, bhi):
2025-07-02 04:52:31.549 bj = b[j]
2025-07-02 04:52:31.549 cruncher.set_seq2(bj)
2025-07-02 04:52:31.549 for i in range(alo, ahi):
2025-07-02 04:52:31.549 ai = a[i]
2025-07-02 04:52:31.549 if ai == bj:
2025-07-02 04:52:31.549 if eqi is None:
2025-07-02 04:52:31.549 eqi, eqj = i, j
2025-07-02 04:52:31.549 continue
2025-07-02 04:52:31.549 cruncher.set_seq1(ai)
2025-07-02 04:52:31.549 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.549 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.549 # compares by a factor of 3.
2025-07-02 04:52:31.549 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.549 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.549 # of the computation is cached by cruncher
2025-07-02 04:52:31.549 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.549 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.549 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.549 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.549 if best_ratio < cutoff:
2025-07-02 04:52:31.550 # no non-identical "pretty close" pair
2025-07-02 04:52:31.550 if eqi is None:
2025-07-02 04:52:31.550 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.550 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.550 return
2025-07-02 04:52:31.550 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.550 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.550 else:
2025-07-02 04:52:31.550 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.550 eqi = None
2025-07-02 04:52:31.550
2025-07-02 04:52:31.550 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.550 # identical
2025-07-02 04:52:31.550
2025-07-02 04:52:31.550 # pump out diffs from before the synch point
2025-07-02 04:52:31.550 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.550
2025-07-02 04:52:31.550 # do intraline marking on the synch pair
2025-07-02 04:52:31.550 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.550 if eqi is None:
2025-07-02 04:52:31.551 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.551 atags = btags = ""
2025-07-02 04:52:31.551 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.551 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.551 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.551 if tag == 'replace':
2025-07-02 04:52:31.551 atags += '^' * la
2025-07-02 04:52:31.551 btags += '^' * lb
2025-07-02 04:52:31.551 elif tag == 'delete':
2025-07-02 04:52:31.551 atags += '-' * la
2025-07-02 04:52:31.551 elif tag == 'insert':
2025-07-02 04:52:31.551 btags += '+' * lb
2025-07-02 04:52:31.551 elif tag == 'equal':
2025-07-02 04:52:31.551 atags += ' ' * la
2025-07-02 04:52:31.551 btags += ' ' * lb
2025-07-02 04:52:31.551 else:
2025-07-02 04:52:31.551 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.551 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.551 else:
2025-07-02 04:52:31.551 # the synch pair is identical
2025-07-02 04:52:31.551 yield ' ' + aelt
2025-07-02 04:52:31.552
2025-07-02 04:52:31.552 # pump out diffs from after the synch point
2025-07-02 04:52:31.552 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.552
2025-07-02 04:52:31.552 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.552 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.552
2025-07-02 04:52:31.552 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.552 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.552 alo = 64, ahi = 1101
2025-07-02 04:52:31.552 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.552 blo = 64, bhi = 1101
2025-07-02 04:52:31.552
2025-07-02 04:52:31.552 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.552 g = []
2025-07-02 04:52:31.552 if alo < ahi:
2025-07-02 04:52:31.552 if blo < bhi:
2025-07-02 04:52:31.552 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.552 else:
2025-07-02 04:52:31.552 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.552 elif blo < bhi:
2025-07-02 04:52:31.552 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.553
2025-07-02 04:52:31.553 > yield from g
2025-07-02 04:52:31.553
2025-07-02 04:52:31.553 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.553 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.553
2025-07-02 04:52:31.553 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.553 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.553 alo = 64, ahi = 1101
2025-07-02 04:52:31.553 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.553 blo = 64, bhi = 1101
2025-07-02 04:52:31.553
2025-07-02 04:52:31.553 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.553 r"""
2025-07-02 04:52:31.553 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.553 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.553 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.553 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.553
2025-07-02 04:52:31.553 Example:
2025-07-02 04:52:31.553
2025-07-02 04:52:31.554 >>> d = Differ()
2025-07-02 04:52:31.554 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.554 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.554 >>> print(''.join(results), end="")
2025-07-02 04:52:31.554 - abcDefghiJkl
2025-07-02 04:52:31.554 + abcdefGhijkl
2025-07-02 04:52:31.554 """
2025-07-02 04:52:31.554
2025-07-02 04:52:31.554 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.554 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.554 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.554 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.554 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.554
2025-07-02 04:52:31.554 # search for the pair that matches best without being identical
2025-07-02 04:52:31.554 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.554 # on junk -- unless we have to)
2025-07-02 04:52:31.554 for j in range(blo, bhi):
2025-07-02 04:52:31.554 bj = b[j]
2025-07-02 04:52:31.555 cruncher.set_seq2(bj)
2025-07-02 04:52:31.555 for i in range(alo, ahi):
2025-07-02 04:52:31.555 ai = a[i]
2025-07-02 04:52:31.555 if ai == bj:
2025-07-02 04:52:31.555 if eqi is None:
2025-07-02 04:52:31.555 eqi, eqj = i, j
2025-07-02 04:52:31.555 continue
2025-07-02 04:52:31.555 cruncher.set_seq1(ai)
2025-07-02 04:52:31.555 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.555 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.555 # compares by a factor of 3.
2025-07-02 04:52:31.555 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.555 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.555 # of the computation is cached by cruncher
2025-07-02 04:52:31.555 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.555 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.555 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.555 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.555 if best_ratio < cutoff:
2025-07-02 04:52:31.555 # no non-identical "pretty close" pair
2025-07-02 04:52:31.555 if eqi is None:
2025-07-02 04:52:31.555 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.556 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.556 return
2025-07-02 04:52:31.556 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.556 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.556 else:
2025-07-02 04:52:31.556 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.556 eqi = None
2025-07-02 04:52:31.556
2025-07-02 04:52:31.556 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.556 # identical
2025-07-02 04:52:31.556
2025-07-02 04:52:31.556 # pump out diffs from before the synch point
2025-07-02 04:52:31.556 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.556
2025-07-02 04:52:31.556 # do intraline marking on the synch pair
2025-07-02 04:52:31.556 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.556 if eqi is None:
2025-07-02 04:52:31.556 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.556 atags = btags = ""
2025-07-02 04:52:31.556 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.556 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.557 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.557 if tag == 'replace':
2025-07-02 04:52:31.557 atags += '^' * la
2025-07-02 04:52:31.557 btags += '^' * lb
2025-07-02 04:52:31.557 elif tag == 'delete':
2025-07-02 04:52:31.557 atags += '-' * la
2025-07-02 04:52:31.557 elif tag == 'insert':
2025-07-02 04:52:31.557 btags += '+' * lb
2025-07-02 04:52:31.557 elif tag == 'equal':
2025-07-02 04:52:31.557 atags += ' ' * la
2025-07-02 04:52:31.557 btags += ' ' * lb
2025-07-02 04:52:31.557 else:
2025-07-02 04:52:31.557 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.557 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.557 else:
2025-07-02 04:52:31.557 # the synch pair is identical
2025-07-02 04:52:31.557 yield ' ' + aelt
2025-07-02 04:52:31.557
2025-07-02 04:52:31.557 # pump out diffs from after the synch point
2025-07-02 04:52:31.557 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.558
2025-07-02 04:52:31.558 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.558 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.558
2025-07-02 04:52:31.558 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.558 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.558 alo = 65, ahi = 1101
2025-07-02 04:52:31.558 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.558 blo = 65, bhi = 1101
2025-07-02 04:52:31.558
2025-07-02 04:52:31.558 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.558 g = []
2025-07-02 04:52:31.558 if alo < ahi:
2025-07-02 04:52:31.558 if blo < bhi:
2025-07-02 04:52:31.558 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.558 else:
2025-07-02 04:52:31.558 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.558 elif blo < bhi:
2025-07-02 04:52:31.558 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.558
2025-07-02 04:52:31.559 > yield from g
2025-07-02 04:52:31.559
2025-07-02 04:52:31.559 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.559 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.559
2025-07-02 04:52:31.559 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.559 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.559 alo = 65, ahi = 1101
2025-07-02 04:52:31.559 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.559 blo = 65, bhi = 1101
2025-07-02 04:52:31.559
2025-07-02 04:52:31.559 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.559 r"""
2025-07-02 04:52:31.559 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.559 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.559 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.559 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.559
2025-07-02 04:52:31.559 Example:
2025-07-02 04:52:31.559
2025-07-02 04:52:31.559 >>> d = Differ()
2025-07-02 04:52:31.560 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.560 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.560 >>> print(''.join(results), end="")
2025-07-02 04:52:31.560 - abcDefghiJkl
2025-07-02 04:52:31.560 + abcdefGhijkl
2025-07-02 04:52:31.560 """
2025-07-02 04:52:31.560
2025-07-02 04:52:31.560 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.560 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.560 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.560 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.560 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.560
2025-07-02 04:52:31.560 # search for the pair that matches best without being identical
2025-07-02 04:52:31.560 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.560 # on junk -- unless we have to)
2025-07-02 04:52:31.560 for j in range(blo, bhi):
2025-07-02 04:52:31.560 bj = b[j]
2025-07-02 04:52:31.560 cruncher.set_seq2(bj)
2025-07-02 04:52:31.560 for i in range(alo, ahi):
2025-07-02 04:52:31.561 ai = a[i]
2025-07-02 04:52:31.561 if ai == bj:
2025-07-02 04:52:31.561 if eqi is None:
2025-07-02 04:52:31.561 eqi, eqj = i, j
2025-07-02 04:52:31.561 continue
2025-07-02 04:52:31.561 cruncher.set_seq1(ai)
2025-07-02 04:52:31.561 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.561 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.561 # compares by a factor of 3.
2025-07-02 04:52:31.561 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.561 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.561 # of the computation is cached by cruncher
2025-07-02 04:52:31.561 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.561 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.561 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.561 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.561 if best_ratio < cutoff:
2025-07-02 04:52:31.561 # no non-identical "pretty close" pair
2025-07-02 04:52:31.561 if eqi is None:
2025-07-02 04:52:31.561 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.561 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.562 return
2025-07-02 04:52:31.562 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.562 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.562 else:
2025-07-02 04:52:31.562 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.562 eqi = None
2025-07-02 04:52:31.562
2025-07-02 04:52:31.562 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.562 # identical
2025-07-02 04:52:31.562
2025-07-02 04:52:31.562 # pump out diffs from before the synch point
2025-07-02 04:52:31.562 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.562
2025-07-02 04:52:31.562 # do intraline marking on the synch pair
2025-07-02 04:52:31.562 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.562 if eqi is None:
2025-07-02 04:52:31.562 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.562 atags = btags = ""
2025-07-02 04:52:31.562 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.562 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.562 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.562 if tag == 'replace':
2025-07-02 04:52:31.563 atags += '^' * la
2025-07-02 04:52:31.563 btags += '^' * lb
2025-07-02 04:52:31.563 elif tag == 'delete':
2025-07-02 04:52:31.563 atags += '-' * la
2025-07-02 04:52:31.563 elif tag == 'insert':
2025-07-02 04:52:31.563 btags += '+' * lb
2025-07-02 04:52:31.563 elif tag == 'equal':
2025-07-02 04:52:31.563 atags += ' ' * la
2025-07-02 04:52:31.563 btags += ' ' * lb
2025-07-02 04:52:31.563 else:
2025-07-02 04:52:31.563 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.563 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.563 else:
2025-07-02 04:52:31.563 # the synch pair is identical
2025-07-02 04:52:31.563 yield ' ' + aelt
2025-07-02 04:52:31.563
2025-07-02 04:52:31.563 # pump out diffs from after the synch point
2025-07-02 04:52:31.563 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.563
2025-07-02 04:52:31.563 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.563 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.564
2025-07-02 04:52:31.564 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.564 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.564 alo = 66, ahi = 1101
2025-07-02 04:52:31.564 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.564 blo = 66, bhi = 1101
2025-07-02 04:52:31.564
2025-07-02 04:52:31.564 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.564 g = []
2025-07-02 04:52:31.564 if alo < ahi:
2025-07-02 04:52:31.564 if blo < bhi:
2025-07-02 04:52:31.564 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.564 else:
2025-07-02 04:52:31.564 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.564 elif blo < bhi:
2025-07-02 04:52:31.564 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.564
2025-07-02 04:52:31.564 > yield from g
2025-07-02 04:52:31.564
2025-07-02 04:52:31.564 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.564 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.565
2025-07-02 04:52:31.565 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.565 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.565 alo = 66, ahi = 1101
2025-07-02 04:52:31.565 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.565 blo = 66, bhi = 1101
2025-07-02 04:52:31.565
2025-07-02 04:52:31.565 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.565 r"""
2025-07-02 04:52:31.565 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.565 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.565 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.565 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.565
2025-07-02 04:52:31.565 Example:
2025-07-02 04:52:31.565
2025-07-02 04:52:31.565 >>> d = Differ()
2025-07-02 04:52:31.565 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.565 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.565 >>> print(''.join(results), end="")
2025-07-02 04:52:31.566 - abcDefghiJkl
2025-07-02 04:52:31.566 + abcdefGhijkl
2025-07-02 04:52:31.566 """
2025-07-02 04:52:31.566
2025-07-02 04:52:31.566 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.566 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.566 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.566 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.566 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.566
2025-07-02 04:52:31.566 # search for the pair that matches best without being identical
2025-07-02 04:52:31.566 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.566 # on junk -- unless we have to)
2025-07-02 04:52:31.566 for j in range(blo, bhi):
2025-07-02 04:52:31.566 bj = b[j]
2025-07-02 04:52:31.566 cruncher.set_seq2(bj)
2025-07-02 04:52:31.566 for i in range(alo, ahi):
2025-07-02 04:52:31.566 ai = a[i]
2025-07-02 04:52:31.566 if ai == bj:
2025-07-02 04:52:31.567 if eqi is None:
2025-07-02 04:52:31.567 eqi, eqj = i, j
2025-07-02 04:52:31.567 continue
2025-07-02 04:52:31.567 cruncher.set_seq1(ai)
2025-07-02 04:52:31.567 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.567 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.567 # compares by a factor of 3.
2025-07-02 04:52:31.567 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.567 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.567 # of the computation is cached by cruncher
2025-07-02 04:52:31.567 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.567 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.567 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.567 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.567 if best_ratio < cutoff:
2025-07-02 04:52:31.567 # no non-identical "pretty close" pair
2025-07-02 04:52:31.567 if eqi is None:
2025-07-02 04:52:31.567 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.567 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.567 return
2025-07-02 04:52:31.567 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.568 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.568 else:
2025-07-02 04:52:31.568 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.568 eqi = None
2025-07-02 04:52:31.568
2025-07-02 04:52:31.568 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.568 # identical
2025-07-02 04:52:31.568
2025-07-02 04:52:31.568 # pump out diffs from before the synch point
2025-07-02 04:52:31.568 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.568
2025-07-02 04:52:31.568 # do intraline marking on the synch pair
2025-07-02 04:52:31.568 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.568 if eqi is None:
2025-07-02 04:52:31.568 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.568 atags = btags = ""
2025-07-02 04:52:31.568 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.568 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.568 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.568 if tag == 'replace':
2025-07-02 04:52:31.568 atags += '^' * la
2025-07-02 04:52:31.569 btags += '^' * lb
2025-07-02 04:52:31.569 elif tag == 'delete':
2025-07-02 04:52:31.569 atags += '-' * la
2025-07-02 04:52:31.569 elif tag == 'insert':
2025-07-02 04:52:31.569 btags += '+' * lb
2025-07-02 04:52:31.569 elif tag == 'equal':
2025-07-02 04:52:31.569 atags += ' ' * la
2025-07-02 04:52:31.569 btags += ' ' * lb
2025-07-02 04:52:31.569 else:
2025-07-02 04:52:31.569 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.569 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.569 else:
2025-07-02 04:52:31.569 # the synch pair is identical
2025-07-02 04:52:31.569 yield ' ' + aelt
2025-07-02 04:52:31.569
2025-07-02 04:52:31.569 # pump out diffs from after the synch point
2025-07-02 04:52:31.569 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.569
2025-07-02 04:52:31.569 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.569 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.569
2025-07-02 04:52:31.569 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.570 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.570 alo = 67, ahi = 1101
2025-07-02 04:52:31.570 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.570 blo = 67, bhi = 1101
2025-07-02 04:52:31.570
2025-07-02 04:52:31.570 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.570 g = []
2025-07-02 04:52:31.570 if alo < ahi:
2025-07-02 04:52:31.570 if blo < bhi:
2025-07-02 04:52:31.570 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.570 else:
2025-07-02 04:52:31.570 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.570 elif blo < bhi:
2025-07-02 04:52:31.570 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.570
2025-07-02 04:52:31.570 > yield from g
2025-07-02 04:52:31.570
2025-07-02 04:52:31.570 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.570 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.570
2025-07-02 04:52:31.570 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.571 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.571 alo = 67, ahi = 1101
2025-07-02 04:52:31.571 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.571 blo = 67, bhi = 1101
2025-07-02 04:52:31.571
2025-07-02 04:52:31.571 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.571 r"""
2025-07-02 04:52:31.571 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.571 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.571 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.571 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.571
2025-07-02 04:52:31.571 Example:
2025-07-02 04:52:31.571
2025-07-02 04:52:31.571 >>> d = Differ()
2025-07-02 04:52:31.571 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.571 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.571 >>> print(''.join(results), end="")
2025-07-02 04:52:31.571 - abcDefghiJkl
2025-07-02 04:52:31.571 + abcdefGhijkl
2025-07-02 04:52:31.572 """
2025-07-02 04:52:31.572
2025-07-02 04:52:31.572 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.572 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.572 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.572 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.572 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.572
2025-07-02 04:52:31.572 # search for the pair that matches best without being identical
2025-07-02 04:52:31.572 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.572 # on junk -- unless we have to)
2025-07-02 04:52:31.572 for j in range(blo, bhi):
2025-07-02 04:52:31.572 bj = b[j]
2025-07-02 04:52:31.572 cruncher.set_seq2(bj)
2025-07-02 04:52:31.572 for i in range(alo, ahi):
2025-07-02 04:52:31.572 ai = a[i]
2025-07-02 04:52:31.572 if ai == bj:
2025-07-02 04:52:31.572 if eqi is None:
2025-07-02 04:52:31.572 eqi, eqj = i, j
2025-07-02 04:52:31.572 continue
2025-07-02 04:52:31.572 cruncher.set_seq1(ai)
2025-07-02 04:52:31.573 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.573 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.573 # compares by a factor of 3.
2025-07-02 04:52:31.573 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.573 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.573 # of the computation is cached by cruncher
2025-07-02 04:52:31.573 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.573 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.573 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.573 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.573 if best_ratio < cutoff:
2025-07-02 04:52:31.573 # no non-identical "pretty close" pair
2025-07-02 04:52:31.573 if eqi is None:
2025-07-02 04:52:31.573 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.573 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.573 return
2025-07-02 04:52:31.573 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.573 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.573 else:
2025-07-02 04:52:31.573 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.574 eqi = None
2025-07-02 04:52:31.574
2025-07-02 04:52:31.574 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.574 # identical
2025-07-02 04:52:31.574
2025-07-02 04:52:31.574 # pump out diffs from before the synch point
2025-07-02 04:52:31.574 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.574
2025-07-02 04:52:31.574 # do intraline marking on the synch pair
2025-07-02 04:52:31.574 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.574 if eqi is None:
2025-07-02 04:52:31.574 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.574 atags = btags = ""
2025-07-02 04:52:31.574 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.574 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.574 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.574 if tag == 'replace':
2025-07-02 04:52:31.574 atags += '^' * la
2025-07-02 04:52:31.574 btags += '^' * lb
2025-07-02 04:52:31.574 elif tag == 'delete':
2025-07-02 04:52:31.575 atags += '-' * la
2025-07-02 04:52:31.575 elif tag == 'insert':
2025-07-02 04:52:31.575 btags += '+' * lb
2025-07-02 04:52:31.575 elif tag == 'equal':
2025-07-02 04:52:31.575 atags += ' ' * la
2025-07-02 04:52:31.575 btags += ' ' * lb
2025-07-02 04:52:31.575 else:
2025-07-02 04:52:31.575 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.575 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.575 else:
2025-07-02 04:52:31.575 # the synch pair is identical
2025-07-02 04:52:31.575 yield ' ' + aelt
2025-07-02 04:52:31.575
2025-07-02 04:52:31.575 # pump out diffs from after the synch point
2025-07-02 04:52:31.575 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.575
2025-07-02 04:52:31.575 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.575 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.575
2025-07-02 04:52:31.575 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.575 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.576 alo = 70, ahi = 1101
2025-07-02 04:52:31.576 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.576 blo = 70, bhi = 1101
2025-07-02 04:52:31.576
2025-07-02 04:52:31.576 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.576 g = []
2025-07-02 04:52:31.576 if alo < ahi:
2025-07-02 04:52:31.576 if blo < bhi:
2025-07-02 04:52:31.576 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.576 else:
2025-07-02 04:52:31.576 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.576 elif blo < bhi:
2025-07-02 04:52:31.576 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.576
2025-07-02 04:52:31.576 > yield from g
2025-07-02 04:52:31.576
2025-07-02 04:52:31.576 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.576 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.576
2025-07-02 04:52:31.576 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.576 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.576 alo = 70, ahi = 1101
2025-07-02 04:52:31.577 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.577 blo = 70, bhi = 1101
2025-07-02 04:52:31.577
2025-07-02 04:52:31.577 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.577 r"""
2025-07-02 04:52:31.577 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.577 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.577 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.577 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.577
2025-07-02 04:52:31.577 Example:
2025-07-02 04:52:31.577
2025-07-02 04:52:31.577 >>> d = Differ()
2025-07-02 04:52:31.577 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.577 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.577 >>> print(''.join(results), end="")
2025-07-02 04:52:31.577 - abcDefghiJkl
2025-07-02 04:52:31.577 + abcdefGhijkl
2025-07-02 04:52:31.577 """
2025-07-02 04:52:31.578
2025-07-02 04:52:31.578 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.578 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.578 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.578 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.578 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.578
2025-07-02 04:52:31.578 # search for the pair that matches best without being identical
2025-07-02 04:52:31.578 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.578 # on junk -- unless we have to)
2025-07-02 04:52:31.578 for j in range(blo, bhi):
2025-07-02 04:52:31.578 bj = b[j]
2025-07-02 04:52:31.578 cruncher.set_seq2(bj)
2025-07-02 04:52:31.578 for i in range(alo, ahi):
2025-07-02 04:52:31.578 ai = a[i]
2025-07-02 04:52:31.578 if ai == bj:
2025-07-02 04:52:31.578 if eqi is None:
2025-07-02 04:52:31.578 eqi, eqj = i, j
2025-07-02 04:52:31.578 continue
2025-07-02 04:52:31.578 cruncher.set_seq1(ai)
2025-07-02 04:52:31.578 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.578 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.579 # compares by a factor of 3.
2025-07-02 04:52:31.579 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.579 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.579 # of the computation is cached by cruncher
2025-07-02 04:52:31.579 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.579 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.579 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.579 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.579 if best_ratio < cutoff:
2025-07-02 04:52:31.579 # no non-identical "pretty close" pair
2025-07-02 04:52:31.579 if eqi is None:
2025-07-02 04:52:31.579 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.579 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.579 return
2025-07-02 04:52:31.579 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.579 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.579 else:
2025-07-02 04:52:31.579 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.579 eqi = None
2025-07-02 04:52:31.579
2025-07-02 04:52:31.579 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.580 # identical
2025-07-02 04:52:31.580
2025-07-02 04:52:31.580 # pump out diffs from before the synch point
2025-07-02 04:52:31.580 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.580
2025-07-02 04:52:31.580 # do intraline marking on the synch pair
2025-07-02 04:52:31.580 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.580 if eqi is None:
2025-07-02 04:52:31.580 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.580 atags = btags = ""
2025-07-02 04:52:31.580 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.580 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.580 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.580 if tag == 'replace':
2025-07-02 04:52:31.580 atags += '^' * la
2025-07-02 04:52:31.580 btags += '^' * lb
2025-07-02 04:52:31.580 elif tag == 'delete':
2025-07-02 04:52:31.580 atags += '-' * la
2025-07-02 04:52:31.580 elif tag == 'insert':
2025-07-02 04:52:31.580 btags += '+' * lb
2025-07-02 04:52:31.580 elif tag == 'equal':
2025-07-02 04:52:31.580 atags += ' ' * la
2025-07-02 04:52:31.581 btags += ' ' * lb
2025-07-02 04:52:31.581 else:
2025-07-02 04:52:31.581 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.581 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.581 else:
2025-07-02 04:52:31.581 # the synch pair is identical
2025-07-02 04:52:31.581 yield ' ' + aelt
2025-07-02 04:52:31.581
2025-07-02 04:52:31.581 # pump out diffs from after the synch point
2025-07-02 04:52:31.581 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.581
2025-07-02 04:52:31.581 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.581 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.581
2025-07-02 04:52:31.581 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.581 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.581 alo = 71, ahi = 1101
2025-07-02 04:52:31.581 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.582 blo = 71, bhi = 1101
2025-07-02 04:52:31.582
2025-07-02 04:52:31.582 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.582 g = []
2025-07-02 04:52:31.582 if alo < ahi:
2025-07-02 04:52:31.582 if blo < bhi:
2025-07-02 04:52:31.582 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.582 else:
2025-07-02 04:52:31.582 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.582 elif blo < bhi:
2025-07-02 04:52:31.582 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.582
2025-07-02 04:52:31.582 > yield from g
2025-07-02 04:52:31.582
2025-07-02 04:52:31.582 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.582 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.582
2025-07-02 04:52:31.582 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.582 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.582 alo = 71, ahi = 1101
2025-07-02 04:52:31.583 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.583 blo = 71, bhi = 1101
2025-07-02 04:52:31.583
2025-07-02 04:52:31.583 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.583 r"""
2025-07-02 04:52:31.583 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.583 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.583 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.583 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.583
2025-07-02 04:52:31.583 Example:
2025-07-02 04:52:31.583
2025-07-02 04:52:31.583 >>> d = Differ()
2025-07-02 04:52:31.583 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.583 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.583 >>> print(''.join(results), end="")
2025-07-02 04:52:31.583 - abcDefghiJkl
2025-07-02 04:52:31.583 + abcdefGhijkl
2025-07-02 04:52:31.584 """
2025-07-02 04:52:31.584
2025-07-02 04:52:31.584 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.584 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.584 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.584 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.584 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.584
2025-07-02 04:52:31.584 # search for the pair that matches best without being identical
2025-07-02 04:52:31.584 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.584 # on junk -- unless we have to)
2025-07-02 04:52:31.584 for j in range(blo, bhi):
2025-07-02 04:52:31.584 bj = b[j]
2025-07-02 04:52:31.584 cruncher.set_seq2(bj)
2025-07-02 04:52:31.584 for i in range(alo, ahi):
2025-07-02 04:52:31.584 ai = a[i]
2025-07-02 04:52:31.584 if ai == bj:
2025-07-02 04:52:31.584 if eqi is None:
2025-07-02 04:52:31.584 eqi, eqj = i, j
2025-07-02 04:52:31.584 continue
2025-07-02 04:52:31.584 cruncher.set_seq1(ai)
2025-07-02 04:52:31.585 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.585 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.585 # compares by a factor of 3.
2025-07-02 04:52:31.585 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.585 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.585 # of the computation is cached by cruncher
2025-07-02 04:52:31.585 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.585 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.585 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.585 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.585 if best_ratio < cutoff:
2025-07-02 04:52:31.585 # no non-identical "pretty close" pair
2025-07-02 04:52:31.585 if eqi is None:
2025-07-02 04:52:31.585 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.585 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.585 return
2025-07-02 04:52:31.585 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.585 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.585 else:
2025-07-02 04:52:31.585 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.586 eqi = None
2025-07-02 04:52:31.586
2025-07-02 04:52:31.586 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.586 # identical
2025-07-02 04:52:31.586
2025-07-02 04:52:31.586 # pump out diffs from before the synch point
2025-07-02 04:52:31.586 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.586
2025-07-02 04:52:31.586 # do intraline marking on the synch pair
2025-07-02 04:52:31.586 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.586 if eqi is None:
2025-07-02 04:52:31.586 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.586 atags = btags = ""
2025-07-02 04:52:31.586 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.586 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.586 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.586 if tag == 'replace':
2025-07-02 04:52:31.586 atags += '^' * la
2025-07-02 04:52:31.586 btags += '^' * lb
2025-07-02 04:52:31.586 elif tag == 'delete':
2025-07-02 04:52:31.586 atags += '-' * la
2025-07-02 04:52:31.587 elif tag == 'insert':
2025-07-02 04:52:31.587 btags += '+' * lb
2025-07-02 04:52:31.587 elif tag == 'equal':
2025-07-02 04:52:31.587 atags += ' ' * la
2025-07-02 04:52:31.587 btags += ' ' * lb
2025-07-02 04:52:31.587 else:
2025-07-02 04:52:31.587 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.587 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.587 else:
2025-07-02 04:52:31.587 # the synch pair is identical
2025-07-02 04:52:31.587 yield ' ' + aelt
2025-07-02 04:52:31.587
2025-07-02 04:52:31.587 # pump out diffs from after the synch point
2025-07-02 04:52:31.587 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.587
2025-07-02 04:52:31.587 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.587 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.587
2025-07-02 04:52:31.588 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.588 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.588 alo = 72, ahi = 1101
2025-07-02 04:52:31.588 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.588 blo = 72, bhi = 1101
2025-07-02 04:52:31.588
2025-07-02 04:52:31.588 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.588 g = []
2025-07-02 04:52:31.588 if alo < ahi:
2025-07-02 04:52:31.588 if blo < bhi:
2025-07-02 04:52:31.588 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.588 else:
2025-07-02 04:52:31.588 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.588 elif blo < bhi:
2025-07-02 04:52:31.588 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.588
2025-07-02 04:52:31.588 > yield from g
2025-07-02 04:52:31.588
2025-07-02 04:52:31.588 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.588 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.588
2025-07-02 04:52:31.589 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.589 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.589 alo = 72, ahi = 1101
2025-07-02 04:52:31.589 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.589 blo = 72, bhi = 1101
2025-07-02 04:52:31.589
2025-07-02 04:52:31.589 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.589 r"""
2025-07-02 04:52:31.589 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.589 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.589 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.589 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.589
2025-07-02 04:52:31.589 Example:
2025-07-02 04:52:31.589
2025-07-02 04:52:31.589 >>> d = Differ()
2025-07-02 04:52:31.589 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.589 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.590 >>> print(''.join(results), end="")
2025-07-02 04:52:31.590 - abcDefghiJkl
2025-07-02 04:52:31.590 + abcdefGhijkl
2025-07-02 04:52:31.590 """
2025-07-02 04:52:31.590
2025-07-02 04:52:31.590 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.590 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.590 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.590 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.590 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.590
2025-07-02 04:52:31.590 # search for the pair that matches best without being identical
2025-07-02 04:52:31.590 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.590 # on junk -- unless we have to)
2025-07-02 04:52:31.590 for j in range(blo, bhi):
2025-07-02 04:52:31.590 bj = b[j]
2025-07-02 04:52:31.590 cruncher.set_seq2(bj)
2025-07-02 04:52:31.590 for i in range(alo, ahi):
2025-07-02 04:52:31.591 ai = a[i]
2025-07-02 04:52:31.591 if ai == bj:
2025-07-02 04:52:31.591 if eqi is None:
2025-07-02 04:52:31.591 eqi, eqj = i, j
2025-07-02 04:52:31.591 continue
2025-07-02 04:52:31.591 cruncher.set_seq1(ai)
2025-07-02 04:52:31.591 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.591 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.591 # compares by a factor of 3.
2025-07-02 04:52:31.591 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.591 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.591 # of the computation is cached by cruncher
2025-07-02 04:52:31.591 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.591 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.591 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.591 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.591 if best_ratio < cutoff:
2025-07-02 04:52:31.591 # no non-identical "pretty close" pair
2025-07-02 04:52:31.591 if eqi is None:
2025-07-02 04:52:31.591 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.591 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.592 return
2025-07-02 04:52:31.592 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.592 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.592 else:
2025-07-02 04:52:31.592 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.592 eqi = None
2025-07-02 04:52:31.592
2025-07-02 04:52:31.592 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.592 # identical
2025-07-02 04:52:31.592
2025-07-02 04:52:31.592 # pump out diffs from before the synch point
2025-07-02 04:52:31.592 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.592
2025-07-02 04:52:31.592 # do intraline marking on the synch pair
2025-07-02 04:52:31.592 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.592 if eqi is None:
2025-07-02 04:52:31.592 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.592 atags = btags = ""
2025-07-02 04:52:31.592 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.592 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.593 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.593 if tag == 'replace':
2025-07-02 04:52:31.593 atags += '^' * la
2025-07-02 04:52:31.593 btags += '^' * lb
2025-07-02 04:52:31.593 elif tag == 'delete':
2025-07-02 04:52:31.593 atags += '-' * la
2025-07-02 04:52:31.593 elif tag == 'insert':
2025-07-02 04:52:31.593 btags += '+' * lb
2025-07-02 04:52:31.593 elif tag == 'equal':
2025-07-02 04:52:31.593 atags += ' ' * la
2025-07-02 04:52:31.593 btags += ' ' * lb
2025-07-02 04:52:31.593 else:
2025-07-02 04:52:31.593 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.593 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.593 else:
2025-07-02 04:52:31.593 # the synch pair is identical
2025-07-02 04:52:31.593 yield ' ' + aelt
2025-07-02 04:52:31.593
2025-07-02 04:52:31.593 # pump out diffs from after the synch point
2025-07-02 04:52:31.593 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.594
2025-07-02 04:52:31.594 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.594 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.594
2025-07-02 04:52:31.594 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.594 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.594 alo = 73, ahi = 1101
2025-07-02 04:52:31.594 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.594 blo = 73, bhi = 1101
2025-07-02 04:52:31.594
2025-07-02 04:52:31.594 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.594 g = []
2025-07-02 04:52:31.594 if alo < ahi:
2025-07-02 04:52:31.594 if blo < bhi:
2025-07-02 04:52:31.594 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.594 else:
2025-07-02 04:52:31.594 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.594 elif blo < bhi:
2025-07-02 04:52:31.594 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.594
2025-07-02 04:52:31.594 > yield from g
2025-07-02 04:52:31.595
2025-07-02 04:52:31.595 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.595 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.595
2025-07-02 04:52:31.595 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.595 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.595 alo = 73, ahi = 1101
2025-07-02 04:52:31.595 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.595 blo = 73, bhi = 1101
2025-07-02 04:52:31.595
2025-07-02 04:52:31.595 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.595 r"""
2025-07-02 04:52:31.595 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.595 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.595 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.595 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.595
2025-07-02 04:52:31.595 Example:
2025-07-02 04:52:31.595
2025-07-02 04:52:31.596 >>> d = Differ()
2025-07-02 04:52:31.596 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.596 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.596 >>> print(''.join(results), end="")
2025-07-02 04:52:31.596 - abcDefghiJkl
2025-07-02 04:52:31.596 + abcdefGhijkl
2025-07-02 04:52:31.596 """
2025-07-02 04:52:31.596
2025-07-02 04:52:31.596 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.596 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.596 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.596 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.596 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.596
2025-07-02 04:52:31.596 # search for the pair that matches best without being identical
2025-07-02 04:52:31.596 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.596 # on junk -- unless we have to)
2025-07-02 04:52:31.596 for j in range(blo, bhi):
2025-07-02 04:52:31.596 bj = b[j]
2025-07-02 04:52:31.597 cruncher.set_seq2(bj)
2025-07-02 04:52:31.597 for i in range(alo, ahi):
2025-07-02 04:52:31.597 ai = a[i]
2025-07-02 04:52:31.597 if ai == bj:
2025-07-02 04:52:31.597 if eqi is None:
2025-07-02 04:52:31.597 eqi, eqj = i, j
2025-07-02 04:52:31.597 continue
2025-07-02 04:52:31.597 cruncher.set_seq1(ai)
2025-07-02 04:52:31.597 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.597 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.597 # compares by a factor of 3.
2025-07-02 04:52:31.597 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.597 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.597 # of the computation is cached by cruncher
2025-07-02 04:52:31.597 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.597 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.597 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.597 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.597 if best_ratio < cutoff:
2025-07-02 04:52:31.597 # no non-identical "pretty close" pair
2025-07-02 04:52:31.598 if eqi is None:
2025-07-02 04:52:31.598 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.598 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.598 return
2025-07-02 04:52:31.598 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.598 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.598 else:
2025-07-02 04:52:31.598 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.598 eqi = None
2025-07-02 04:52:31.598
2025-07-02 04:52:31.598 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.598 # identical
2025-07-02 04:52:31.598
2025-07-02 04:52:31.598 # pump out diffs from before the synch point
2025-07-02 04:52:31.598 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.598
2025-07-02 04:52:31.598 # do intraline marking on the synch pair
2025-07-02 04:52:31.598 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.599 if eqi is None:
2025-07-02 04:52:31.599 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.599 atags = btags = ""
2025-07-02 04:52:31.599 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.599 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.599 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.599 if tag == 'replace':
2025-07-02 04:52:31.599 atags += '^' * la
2025-07-02 04:52:31.599 btags += '^' * lb
2025-07-02 04:52:31.599 elif tag == 'delete':
2025-07-02 04:52:31.599 atags += '-' * la
2025-07-02 04:52:31.599 elif tag == 'insert':
2025-07-02 04:52:31.599 btags += '+' * lb
2025-07-02 04:52:31.599 elif tag == 'equal':
2025-07-02 04:52:31.599 atags += ' ' * la
2025-07-02 04:52:31.599 btags += ' ' * lb
2025-07-02 04:52:31.599 else:
2025-07-02 04:52:31.599 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.599 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.599 else:
2025-07-02 04:52:31.599 # the synch pair is identical
2025-07-02 04:52:31.600 yield ' ' + aelt
2025-07-02 04:52:31.600
2025-07-02 04:52:31.600 # pump out diffs from after the synch point
2025-07-02 04:52:31.600 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.600
2025-07-02 04:52:31.600 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.600 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.600
2025-07-02 04:52:31.600 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.600 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.600 alo = 74, ahi = 1101
2025-07-02 04:52:31.600 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.600 blo = 74, bhi = 1101
2025-07-02 04:52:31.600
2025-07-02 04:52:31.600 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.600 g = []
2025-07-02 04:52:31.600 if alo < ahi:
2025-07-02 04:52:31.600 if blo < bhi:
2025-07-02 04:52:31.600 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.600 else:
2025-07-02 04:52:31.601 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.601 elif blo < bhi:
2025-07-02 04:52:31.601 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.601
2025-07-02 04:52:31.601 > yield from g
2025-07-02 04:52:31.601
2025-07-02 04:52:31.601 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.601 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.601
2025-07-02 04:52:31.601 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.601 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.601 alo = 74, ahi = 1101
2025-07-02 04:52:31.601 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.601 blo = 74, bhi = 1101
2025-07-02 04:52:31.601
2025-07-02 04:52:31.601 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.601 r"""
2025-07-02 04:52:31.601 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.601 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.601 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.601 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.602
2025-07-02 04:52:31.602 Example:
2025-07-02 04:52:31.602
2025-07-02 04:52:31.602 >>> d = Differ()
2025-07-02 04:52:31.602 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.602 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.602 >>> print(''.join(results), end="")
2025-07-02 04:52:31.602 - abcDefghiJkl
2025-07-02 04:52:31.602 + abcdefGhijkl
2025-07-02 04:52:31.602 """
2025-07-02 04:52:31.602
2025-07-02 04:52:31.602 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.602 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.602 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.602 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.602 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.602
2025-07-02 04:52:31.602 # search for the pair that matches best without being identical
2025-07-02 04:52:31.602 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.603 # on junk -- unless we have to)
2025-07-02 04:52:31.603 for j in range(blo, bhi):
2025-07-02 04:52:31.603 bj = b[j]
2025-07-02 04:52:31.603 cruncher.set_seq2(bj)
2025-07-02 04:52:31.603 for i in range(alo, ahi):
2025-07-02 04:52:31.603 ai = a[i]
2025-07-02 04:52:31.603 if ai == bj:
2025-07-02 04:52:31.603 if eqi is None:
2025-07-02 04:52:31.603 eqi, eqj = i, j
2025-07-02 04:52:31.603 continue
2025-07-02 04:52:31.603 cruncher.set_seq1(ai)
2025-07-02 04:52:31.603 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.603 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.603 # compares by a factor of 3.
2025-07-02 04:52:31.603 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.603 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.603 # of the computation is cached by cruncher
2025-07-02 04:52:31.603 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.603 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.603 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.604 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.604 if best_ratio < cutoff:
2025-07-02 04:52:31.604 # no non-identical "pretty close" pair
2025-07-02 04:52:31.604 if eqi is None:
2025-07-02 04:52:31.604 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.604 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.604 return
2025-07-02 04:52:31.604 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.604 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.604 else:
2025-07-02 04:52:31.604 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.604 eqi = None
2025-07-02 04:52:31.604
2025-07-02 04:52:31.604 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.604 # identical
2025-07-02 04:52:31.604
2025-07-02 04:52:31.604 # pump out diffs from before the synch point
2025-07-02 04:52:31.604 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.604
2025-07-02 04:52:31.604 # do intraline marking on the synch pair
2025-07-02 04:52:31.604 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.605 if eqi is None:
2025-07-02 04:52:31.605 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.605 atags = btags = ""
2025-07-02 04:52:31.605 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.605 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.605 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.605 if tag == 'replace':
2025-07-02 04:52:31.605 atags += '^' * la
2025-07-02 04:52:31.605 btags += '^' * lb
2025-07-02 04:52:31.605 elif tag == 'delete':
2025-07-02 04:52:31.605 atags += '-' * la
2025-07-02 04:52:31.605 elif tag == 'insert':
2025-07-02 04:52:31.605 btags += '+' * lb
2025-07-02 04:52:31.605 elif tag == 'equal':
2025-07-02 04:52:31.605 atags += ' ' * la
2025-07-02 04:52:31.605 btags += ' ' * lb
2025-07-02 04:52:31.605 else:
2025-07-02 04:52:31.605 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.605 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.605 else:
2025-07-02 04:52:31.605 # the synch pair is identical
2025-07-02 04:52:31.606 yield ' ' + aelt
2025-07-02 04:52:31.606
2025-07-02 04:52:31.606 # pump out diffs from after the synch point
2025-07-02 04:52:31.606 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.606
2025-07-02 04:52:31.606 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.606 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.606
2025-07-02 04:52:31.606 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.606 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.606 alo = 75, ahi = 1101
2025-07-02 04:52:31.606 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.606 blo = 75, bhi = 1101
2025-07-02 04:52:31.606
2025-07-02 04:52:31.606 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.606 g = []
2025-07-02 04:52:31.606 if alo < ahi:
2025-07-02 04:52:31.606 if blo < bhi:
2025-07-02 04:52:31.606 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.606 else:
2025-07-02 04:52:31.607 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.607 elif blo < bhi:
2025-07-02 04:52:31.607 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.607
2025-07-02 04:52:31.607 > yield from g
2025-07-02 04:52:31.607
2025-07-02 04:52:31.607 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.607 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.607
2025-07-02 04:52:31.607 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.607 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.607 alo = 75, ahi = 1101
2025-07-02 04:52:31.607 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.607 blo = 75, bhi = 1101
2025-07-02 04:52:31.607
2025-07-02 04:52:31.607 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.607 r"""
2025-07-02 04:52:31.607 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.607 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.608 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.608 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.608
2025-07-02 04:52:31.608 Example:
2025-07-02 04:52:31.608
2025-07-02 04:52:31.608 >>> d = Differ()
2025-07-02 04:52:31.608 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.608 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.608 >>> print(''.join(results), end="")
2025-07-02 04:52:31.608 - abcDefghiJkl
2025-07-02 04:52:31.608 + abcdefGhijkl
2025-07-02 04:52:31.608 """
2025-07-02 04:52:31.608
2025-07-02 04:52:31.608 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.608 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.608 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.608 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.608 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.608
2025-07-02 04:52:31.609 # search for the pair that matches best without being identical
2025-07-02 04:52:31.609 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.609 # on junk -- unless we have to)
2025-07-02 04:52:31.609 for j in range(blo, bhi):
2025-07-02 04:52:31.609 bj = b[j]
2025-07-02 04:52:31.609 cruncher.set_seq2(bj)
2025-07-02 04:52:31.609 for i in range(alo, ahi):
2025-07-02 04:52:31.609 ai = a[i]
2025-07-02 04:52:31.609 if ai == bj:
2025-07-02 04:52:31.609 if eqi is None:
2025-07-02 04:52:31.609 eqi, eqj = i, j
2025-07-02 04:52:31.609 continue
2025-07-02 04:52:31.609 cruncher.set_seq1(ai)
2025-07-02 04:52:31.609 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.609 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.609 # compares by a factor of 3.
2025-07-02 04:52:31.609 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.609 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.609 # of the computation is cached by cruncher
2025-07-02 04:52:31.609 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.610 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.610 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.610 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.610 if best_ratio < cutoff:
2025-07-02 04:52:31.610 # no non-identical "pretty close" pair
2025-07-02 04:52:31.610 if eqi is None:
2025-07-02 04:52:31.610 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.610 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.610 return
2025-07-02 04:52:31.610 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.610 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.610 else:
2025-07-02 04:52:31.610 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.610 eqi = None
2025-07-02 04:52:31.610
2025-07-02 04:52:31.610 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.610 # identical
2025-07-02 04:52:31.610
2025-07-02 04:52:31.610 # pump out diffs from before the synch point
2025-07-02 04:52:31.610 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.610
2025-07-02 04:52:31.611 # do intraline marking on the synch pair
2025-07-02 04:52:31.611 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.611 if eqi is None:
2025-07-02 04:52:31.611 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.611 atags = btags = ""
2025-07-02 04:52:31.611 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.611 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.611 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.611 if tag == 'replace':
2025-07-02 04:52:31.611 atags += '^' * la
2025-07-02 04:52:31.611 btags += '^' * lb
2025-07-02 04:52:31.611 elif tag == 'delete':
2025-07-02 04:52:31.611 atags += '-' * la
2025-07-02 04:52:31.611 elif tag == 'insert':
2025-07-02 04:52:31.611 btags += '+' * lb
2025-07-02 04:52:31.611 elif tag == 'equal':
2025-07-02 04:52:31.611 atags += ' ' * la
2025-07-02 04:52:31.611 btags += ' ' * lb
2025-07-02 04:52:31.611 else:
2025-07-02 04:52:31.612 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.612 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.612 else:
2025-07-02 04:52:31.612 # the synch pair is identical
2025-07-02 04:52:31.612 yield ' ' + aelt
2025-07-02 04:52:31.612
2025-07-02 04:52:31.612 # pump out diffs from after the synch point
2025-07-02 04:52:31.612 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.612
2025-07-02 04:52:31.612 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.612 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.612
2025-07-02 04:52:31.612 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.612 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.612 alo = 76, ahi = 1101
2025-07-02 04:52:31.612 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.612 blo = 76, bhi = 1101
2025-07-02 04:52:31.612
2025-07-02 04:52:31.612 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.613 g = []
2025-07-02 04:52:31.613 if alo < ahi:
2025-07-02 04:52:31.613 if blo < bhi:
2025-07-02 04:52:31.613 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.613 else:
2025-07-02 04:52:31.613 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.613 elif blo < bhi:
2025-07-02 04:52:31.613 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.613
2025-07-02 04:52:31.613 > yield from g
2025-07-02 04:52:31.613
2025-07-02 04:52:31.613 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.613 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.613
2025-07-02 04:52:31.613 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.613 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.613 alo = 76, ahi = 1101
2025-07-02 04:52:31.613 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.613 blo = 76, bhi = 1101
2025-07-02 04:52:31.613
2025-07-02 04:52:31.614 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.614 r"""
2025-07-02 04:52:31.614 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.614 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.614 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.614 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.614
2025-07-02 04:52:31.614 Example:
2025-07-02 04:52:31.614
2025-07-02 04:52:31.614 >>> d = Differ()
2025-07-02 04:52:31.614 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.614 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.614 >>> print(''.join(results), end="")
2025-07-02 04:52:31.614 - abcDefghiJkl
2025-07-02 04:52:31.614 + abcdefGhijkl
2025-07-02 04:52:31.614 """
2025-07-02 04:52:31.614
2025-07-02 04:52:31.614 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.615 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.615 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.615 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.615 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.615
2025-07-02 04:52:31.615 # search for the pair that matches best without being identical
2025-07-02 04:52:31.615 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.615 # on junk -- unless we have to)
2025-07-02 04:52:31.615 for j in range(blo, bhi):
2025-07-02 04:52:31.615 bj = b[j]
2025-07-02 04:52:31.615 cruncher.set_seq2(bj)
2025-07-02 04:52:31.615 for i in range(alo, ahi):
2025-07-02 04:52:31.615 ai = a[i]
2025-07-02 04:52:31.615 if ai == bj:
2025-07-02 04:52:31.615 if eqi is None:
2025-07-02 04:52:31.615 eqi, eqj = i, j
2025-07-02 04:52:31.615 continue
2025-07-02 04:52:31.615 cruncher.set_seq1(ai)
2025-07-02 04:52:31.615 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.615 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.616 # compares by a factor of 3.
2025-07-02 04:52:31.616 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.616 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.616 # of the computation is cached by cruncher
2025-07-02 04:52:31.616 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.616 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.616 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.616 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.616 if best_ratio < cutoff:
2025-07-02 04:52:31.616 # no non-identical "pretty close" pair
2025-07-02 04:52:31.616 if eqi is None:
2025-07-02 04:52:31.616 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.616 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.616 return
2025-07-02 04:52:31.616 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.616 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.616 else:
2025-07-02 04:52:31.616 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.616 eqi = None
2025-07-02 04:52:31.616
2025-07-02 04:52:31.616 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.617 # identical
2025-07-02 04:52:31.617
2025-07-02 04:52:31.617 # pump out diffs from before the synch point
2025-07-02 04:52:31.617 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.617
2025-07-02 04:52:31.617 # do intraline marking on the synch pair
2025-07-02 04:52:31.617 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.617 if eqi is None:
2025-07-02 04:52:31.617 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.617 atags = btags = ""
2025-07-02 04:52:31.617 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.617 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.617 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.617 if tag == 'replace':
2025-07-02 04:52:31.617 atags += '^' * la
2025-07-02 04:52:31.617 btags += '^' * lb
2025-07-02 04:52:31.617 elif tag == 'delete':
2025-07-02 04:52:31.617 atags += '-' * la
2025-07-02 04:52:31.617 elif tag == 'insert':
2025-07-02 04:52:31.617 btags += '+' * lb
2025-07-02 04:52:31.618 elif tag == 'equal':
2025-07-02 04:52:31.618 atags += ' ' * la
2025-07-02 04:52:31.618 btags += ' ' * lb
2025-07-02 04:52:31.618 else:
2025-07-02 04:52:31.618 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.618 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.618 else:
2025-07-02 04:52:31.618 # the synch pair is identical
2025-07-02 04:52:31.618 yield ' ' + aelt
2025-07-02 04:52:31.618
2025-07-02 04:52:31.618 # pump out diffs from after the synch point
2025-07-02 04:52:31.618 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.618
2025-07-02 04:52:31.618 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.618 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.618
2025-07-02 04:52:31.618 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.618 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.618 alo = 77, ahi = 1101
2025-07-02 04:52:31.618 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.619 blo = 77, bhi = 1101
2025-07-02 04:52:31.619
2025-07-02 04:52:31.619 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.619 g = []
2025-07-02 04:52:31.619 if alo < ahi:
2025-07-02 04:52:31.619 if blo < bhi:
2025-07-02 04:52:31.619 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.619 else:
2025-07-02 04:52:31.619 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.619 elif blo < bhi:
2025-07-02 04:52:31.619 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.619
2025-07-02 04:52:31.619 > yield from g
2025-07-02 04:52:31.619
2025-07-02 04:52:31.619 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.619 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.619
2025-07-02 04:52:31.619 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.619 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.619 alo = 77, ahi = 1101
2025-07-02 04:52:31.619 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.620 blo = 77, bhi = 1101
2025-07-02 04:52:31.620
2025-07-02 04:52:31.620 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.620 r"""
2025-07-02 04:52:31.620 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.620 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.620 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.620 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.620
2025-07-02 04:52:31.620 Example:
2025-07-02 04:52:31.620
2025-07-02 04:52:31.620 >>> d = Differ()
2025-07-02 04:52:31.620 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.620 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.620 >>> print(''.join(results), end="")
2025-07-02 04:52:31.620 - abcDefghiJkl
2025-07-02 04:52:31.620 + abcdefGhijkl
2025-07-02 04:52:31.620 """
2025-07-02 04:52:31.621
2025-07-02 04:52:31.621 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.621 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.621 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.621 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.621 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.621
2025-07-02 04:52:31.621 # search for the pair that matches best without being identical
2025-07-02 04:52:31.621 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.621 # on junk -- unless we have to)
2025-07-02 04:52:31.621 for j in range(blo, bhi):
2025-07-02 04:52:31.621 bj = b[j]
2025-07-02 04:52:31.621 cruncher.set_seq2(bj)
2025-07-02 04:52:31.621 for i in range(alo, ahi):
2025-07-02 04:52:31.621 ai = a[i]
2025-07-02 04:52:31.621 if ai == bj:
2025-07-02 04:52:31.621 if eqi is None:
2025-07-02 04:52:31.621 eqi, eqj = i, j
2025-07-02 04:52:31.621 continue
2025-07-02 04:52:31.621 cruncher.set_seq1(ai)
2025-07-02 04:52:31.622 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.622 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.622 # compares by a factor of 3.
2025-07-02 04:52:31.622 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.622 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.622 # of the computation is cached by cruncher
2025-07-02 04:52:31.622 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.622 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.622 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.622 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.622 if best_ratio < cutoff:
2025-07-02 04:52:31.622 # no non-identical "pretty close" pair
2025-07-02 04:52:31.622 if eqi is None:
2025-07-02 04:52:31.622 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.622 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.622 return
2025-07-02 04:52:31.622 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.622 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.622 else:
2025-07-02 04:52:31.622 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.623 eqi = None
2025-07-02 04:52:31.623
2025-07-02 04:52:31.623 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.623 # identical
2025-07-02 04:52:31.623
2025-07-02 04:52:31.623 # pump out diffs from before the synch point
2025-07-02 04:52:31.623 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.623
2025-07-02 04:52:31.623 # do intraline marking on the synch pair
2025-07-02 04:52:31.623 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.623 if eqi is None:
2025-07-02 04:52:31.623 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.623 atags = btags = ""
2025-07-02 04:52:31.623 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.623 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.623 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.623 if tag == 'replace':
2025-07-02 04:52:31.623 atags += '^' * la
2025-07-02 04:52:31.623 btags += '^' * lb
2025-07-02 04:52:31.623 elif tag == 'delete':
2025-07-02 04:52:31.623 atags += '-' * la
2025-07-02 04:52:31.624 elif tag == 'insert':
2025-07-02 04:52:31.624 btags += '+' * lb
2025-07-02 04:52:31.624 elif tag == 'equal':
2025-07-02 04:52:31.624 atags += ' ' * la
2025-07-02 04:52:31.624 btags += ' ' * lb
2025-07-02 04:52:31.624 else:
2025-07-02 04:52:31.624 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.624 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.624 else:
2025-07-02 04:52:31.624 # the synch pair is identical
2025-07-02 04:52:31.624 yield ' ' + aelt
2025-07-02 04:52:31.624
2025-07-02 04:52:31.624 # pump out diffs from after the synch point
2025-07-02 04:52:31.624 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.624
2025-07-02 04:52:31.624 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.624 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.624
2025-07-02 04:52:31.624 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.624 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.625 alo = 78, ahi = 1101
2025-07-02 04:52:31.625 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.625 blo = 78, bhi = 1101
2025-07-02 04:52:31.625
2025-07-02 04:52:31.625 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.625 g = []
2025-07-02 04:52:31.625 if alo < ahi:
2025-07-02 04:52:31.625 if blo < bhi:
2025-07-02 04:52:31.625 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.625 else:
2025-07-02 04:52:31.625 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.625 elif blo < bhi:
2025-07-02 04:52:31.625 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.625
2025-07-02 04:52:31.625 > yield from g
2025-07-02 04:52:31.625
2025-07-02 04:52:31.625 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.625 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.625
2025-07-02 04:52:31.625 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.625 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.626 alo = 78, ahi = 1101
2025-07-02 04:52:31.626 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.626 blo = 78, bhi = 1101
2025-07-02 04:52:31.626
2025-07-02 04:52:31.626 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.626 r"""
2025-07-02 04:52:31.626 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.626 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.626 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.626 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.626
2025-07-02 04:52:31.626 Example:
2025-07-02 04:52:31.626
2025-07-02 04:52:31.626 >>> d = Differ()
2025-07-02 04:52:31.626 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.626 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.626 >>> print(''.join(results), end="")
2025-07-02 04:52:31.626 - abcDefghiJkl
2025-07-02 04:52:31.626 + abcdefGhijkl
2025-07-02 04:52:31.627 """
2025-07-02 04:52:31.627
2025-07-02 04:52:31.627 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.627 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.627 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.627 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.627 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.627
2025-07-02 04:52:31.627 # search for the pair that matches best without being identical
2025-07-02 04:52:31.627 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.627 # on junk -- unless we have to)
2025-07-02 04:52:31.627 for j in range(blo, bhi):
2025-07-02 04:52:31.627 bj = b[j]
2025-07-02 04:52:31.627 cruncher.set_seq2(bj)
2025-07-02 04:52:31.627 for i in range(alo, ahi):
2025-07-02 04:52:31.627 ai = a[i]
2025-07-02 04:52:31.627 if ai == bj:
2025-07-02 04:52:31.627 if eqi is None:
2025-07-02 04:52:31.627 eqi, eqj = i, j
2025-07-02 04:52:31.628 continue
2025-07-02 04:52:31.628 cruncher.set_seq1(ai)
2025-07-02 04:52:31.628 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.628 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.628 # compares by a factor of 3.
2025-07-02 04:52:31.628 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.628 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.628 # of the computation is cached by cruncher
2025-07-02 04:52:31.628 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.628 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.628 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.628 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.628 if best_ratio < cutoff:
2025-07-02 04:52:31.628 # no non-identical "pretty close" pair
2025-07-02 04:52:31.628 if eqi is None:
2025-07-02 04:52:31.628 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.628 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.628 return
2025-07-02 04:52:31.628 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.629 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.629 else:
2025-07-02 04:52:31.629 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.629 eqi = None
2025-07-02 04:52:31.629
2025-07-02 04:52:31.629 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.629 # identical
2025-07-02 04:52:31.629
2025-07-02 04:52:31.629 # pump out diffs from before the synch point
2025-07-02 04:52:31.629 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.629
2025-07-02 04:52:31.629 # do intraline marking on the synch pair
2025-07-02 04:52:31.629 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.629 if eqi is None:
2025-07-02 04:52:31.629 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.629 atags = btags = ""
2025-07-02 04:52:31.629 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.629 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.629 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.629 if tag == 'replace':
2025-07-02 04:52:31.630 atags += '^' * la
2025-07-02 04:52:31.630 btags += '^' * lb
2025-07-02 04:52:31.630 elif tag == 'delete':
2025-07-02 04:52:31.630 atags += '-' * la
2025-07-02 04:52:31.630 elif tag == 'insert':
2025-07-02 04:52:31.630 btags += '+' * lb
2025-07-02 04:52:31.630 elif tag == 'equal':
2025-07-02 04:52:31.630 atags += ' ' * la
2025-07-02 04:52:31.630 btags += ' ' * lb
2025-07-02 04:52:31.630 else:
2025-07-02 04:52:31.630 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.630 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.630 else:
2025-07-02 04:52:31.630 # the synch pair is identical
2025-07-02 04:52:31.630 yield ' ' + aelt
2025-07-02 04:52:31.630
2025-07-02 04:52:31.630 # pump out diffs from after the synch point
2025-07-02 04:52:31.630 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.630
2025-07-02 04:52:31.630 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.630 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.631
2025-07-02 04:52:31.631 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.631 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.631 alo = 79, ahi = 1101
2025-07-02 04:52:31.631 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.631 blo = 79, bhi = 1101
2025-07-02 04:52:31.631
2025-07-02 04:52:31.631 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.631 g = []
2025-07-02 04:52:31.631 if alo < ahi:
2025-07-02 04:52:31.631 if blo < bhi:
2025-07-02 04:52:31.631 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.631 else:
2025-07-02 04:52:31.631 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.631 elif blo < bhi:
2025-07-02 04:52:31.631 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.631
2025-07-02 04:52:31.631 > yield from g
2025-07-02 04:52:31.631
2025-07-02 04:52:31.631 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.631 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.632
2025-07-02 04:52:31.632 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.632 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.632 alo = 79, ahi = 1101
2025-07-02 04:52:31.632 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.632 blo = 79, bhi = 1101
2025-07-02 04:52:31.632
2025-07-02 04:52:31.632 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.632 r"""
2025-07-02 04:52:31.632 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.632 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.632 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.632 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.632
2025-07-02 04:52:31.632 Example:
2025-07-02 04:52:31.632
2025-07-02 04:52:31.632 >>> d = Differ()
2025-07-02 04:52:31.632 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.632 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.633 >>> print(''.join(results), end="")
2025-07-02 04:52:31.633 - abcDefghiJkl
2025-07-02 04:52:31.633 + abcdefGhijkl
2025-07-02 04:52:31.633 """
2025-07-02 04:52:31.633
2025-07-02 04:52:31.633 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.633 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.633 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.633 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.633 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.633
2025-07-02 04:52:31.633 # search for the pair that matches best without being identical
2025-07-02 04:52:31.633 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.633 # on junk -- unless we have to)
2025-07-02 04:52:31.633 for j in range(blo, bhi):
2025-07-02 04:52:31.633 bj = b[j]
2025-07-02 04:52:31.633 cruncher.set_seq2(bj)
2025-07-02 04:52:31.633 for i in range(alo, ahi):
2025-07-02 04:52:31.633 ai = a[i]
2025-07-02 04:52:31.634 if ai == bj:
2025-07-02 04:52:31.634 if eqi is None:
2025-07-02 04:52:31.634 eqi, eqj = i, j
2025-07-02 04:52:31.634 continue
2025-07-02 04:52:31.634 cruncher.set_seq1(ai)
2025-07-02 04:52:31.634 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.634 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.634 # compares by a factor of 3.
2025-07-02 04:52:31.634 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.634 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.634 # of the computation is cached by cruncher
2025-07-02 04:52:31.634 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.634 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.634 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.634 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.634 if best_ratio < cutoff:
2025-07-02 04:52:31.634 # no non-identical "pretty close" pair
2025-07-02 04:52:31.634 if eqi is None:
2025-07-02 04:52:31.634 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.634 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.635 return
2025-07-02 04:52:31.635 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.635 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.635 else:
2025-07-02 04:52:31.635 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.635 eqi = None
2025-07-02 04:52:31.635
2025-07-02 04:52:31.635 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.635 # identical
2025-07-02 04:52:31.635
2025-07-02 04:52:31.635 # pump out diffs from before the synch point
2025-07-02 04:52:31.635 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.635
2025-07-02 04:52:31.635 # do intraline marking on the synch pair
2025-07-02 04:52:31.635 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.635 if eqi is None:
2025-07-02 04:52:31.635 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.635 atags = btags = ""
2025-07-02 04:52:31.635 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.635 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.635 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.635 if tag == 'replace':
2025-07-02 04:52:31.636 atags += '^' * la
2025-07-02 04:52:31.636 btags += '^' * lb
2025-07-02 04:52:31.636 elif tag == 'delete':
2025-07-02 04:52:31.636 atags += '-' * la
2025-07-02 04:52:31.636 elif tag == 'insert':
2025-07-02 04:52:31.636 btags += '+' * lb
2025-07-02 04:52:31.636 elif tag == 'equal':
2025-07-02 04:52:31.636 atags += ' ' * la
2025-07-02 04:52:31.636 btags += ' ' * lb
2025-07-02 04:52:31.636 else:
2025-07-02 04:52:31.636 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.636 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.636 else:
2025-07-02 04:52:31.636 # the synch pair is identical
2025-07-02 04:52:31.636 yield ' ' + aelt
2025-07-02 04:52:31.636
2025-07-02 04:52:31.636 # pump out diffs from after the synch point
2025-07-02 04:52:31.636 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.636
2025-07-02 04:52:31.636 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.636 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.636
2025-07-02 04:52:31.637 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.637 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.637 alo = 80, ahi = 1101
2025-07-02 04:52:31.637 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.637 blo = 80, bhi = 1101
2025-07-02 04:52:31.637
2025-07-02 04:52:31.637 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.637 g = []
2025-07-02 04:52:31.637 if alo < ahi:
2025-07-02 04:52:31.637 if blo < bhi:
2025-07-02 04:52:31.637 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.637 else:
2025-07-02 04:52:31.637 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.637 elif blo < bhi:
2025-07-02 04:52:31.637 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.637
2025-07-02 04:52:31.637 > yield from g
2025-07-02 04:52:31.637
2025-07-02 04:52:31.637 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.637 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.637
2025-07-02 04:52:31.638 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.638 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.638 alo = 80, ahi = 1101
2025-07-02 04:52:31.638 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.638 blo = 80, bhi = 1101
2025-07-02 04:52:31.638
2025-07-02 04:52:31.638 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.638 r"""
2025-07-02 04:52:31.638 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.638 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.638 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.638 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.638
2025-07-02 04:52:31.638 Example:
2025-07-02 04:52:31.638
2025-07-02 04:52:31.638 >>> d = Differ()
2025-07-02 04:52:31.638 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.638 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.638 >>> print(''.join(results), end="")
2025-07-02 04:52:31.638 - abcDefghiJkl
2025-07-02 04:52:31.639 + abcdefGhijkl
2025-07-02 04:52:31.639 """
2025-07-02 04:52:31.639
2025-07-02 04:52:31.639 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.639 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.639 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.639 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.639 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.639
2025-07-02 04:52:31.639 # search for the pair that matches best without being identical
2025-07-02 04:52:31.639 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.639 # on junk -- unless we have to)
2025-07-02 04:52:31.639 for j in range(blo, bhi):
2025-07-02 04:52:31.639 bj = b[j]
2025-07-02 04:52:31.639 cruncher.set_seq2(bj)
2025-07-02 04:52:31.639 for i in range(alo, ahi):
2025-07-02 04:52:31.639 ai = a[i]
2025-07-02 04:52:31.639 if ai == bj:
2025-07-02 04:52:31.639 if eqi is None:
2025-07-02 04:52:31.639 eqi, eqj = i, j
2025-07-02 04:52:31.639 continue
2025-07-02 04:52:31.640 cruncher.set_seq1(ai)
2025-07-02 04:52:31.640 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.640 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.640 # compares by a factor of 3.
2025-07-02 04:52:31.640 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.640 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.640 # of the computation is cached by cruncher
2025-07-02 04:52:31.640 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.640 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.640 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.640 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.640 if best_ratio < cutoff:
2025-07-02 04:52:31.640 # no non-identical "pretty close" pair
2025-07-02 04:52:31.640 if eqi is None:
2025-07-02 04:52:31.640 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.640 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.640 return
2025-07-02 04:52:31.640 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.640 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.641 else:
2025-07-02 04:52:31.641 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.641 eqi = None
2025-07-02 04:52:31.641
2025-07-02 04:52:31.641 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.641 # identical
2025-07-02 04:52:31.641
2025-07-02 04:52:31.641 # pump out diffs from before the synch point
2025-07-02 04:52:31.641 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.641
2025-07-02 04:52:31.641 # do intraline marking on the synch pair
2025-07-02 04:52:31.641 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.641 if eqi is None:
2025-07-02 04:52:31.641 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.641 atags = btags = ""
2025-07-02 04:52:31.641 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.641 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.641 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.641 if tag == 'replace':
2025-07-02 04:52:31.641 atags += '^' * la
2025-07-02 04:52:31.641 btags += '^' * lb
2025-07-02 04:52:31.642 elif tag == 'delete':
2025-07-02 04:52:31.642 atags += '-' * la
2025-07-02 04:52:31.642 elif tag == 'insert':
2025-07-02 04:52:31.642 btags += '+' * lb
2025-07-02 04:52:31.642 elif tag == 'equal':
2025-07-02 04:52:31.642 atags += ' ' * la
2025-07-02 04:52:31.642 btags += ' ' * lb
2025-07-02 04:52:31.642 else:
2025-07-02 04:52:31.642 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.642 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.642 else:
2025-07-02 04:52:31.642 # the synch pair is identical
2025-07-02 04:52:31.642 yield ' ' + aelt
2025-07-02 04:52:31.642
2025-07-02 04:52:31.642 # pump out diffs from after the synch point
2025-07-02 04:52:31.642 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.642
2025-07-02 04:52:31.642 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.642 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.642
2025-07-02 04:52:31.643 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.643 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.643 alo = 81, ahi = 1101
2025-07-02 04:52:31.643 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.643 blo = 81, bhi = 1101
2025-07-02 04:52:31.643
2025-07-02 04:52:31.643 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.643 g = []
2025-07-02 04:52:31.643 if alo < ahi:
2025-07-02 04:52:31.643 if blo < bhi:
2025-07-02 04:52:31.643 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.643 else:
2025-07-02 04:52:31.643 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.643 elif blo < bhi:
2025-07-02 04:52:31.643 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.643
2025-07-02 04:52:31.643 > yield from g
2025-07-02 04:52:31.643
2025-07-02 04:52:31.643 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.643 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.644
2025-07-02 04:52:31.644 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.644 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.644 alo = 81, ahi = 1101
2025-07-02 04:52:31.644 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.644 blo = 81, bhi = 1101
2025-07-02 04:52:31.644
2025-07-02 04:52:31.644 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.644 r"""
2025-07-02 04:52:31.644 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.644 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.644 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.644 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.644
2025-07-02 04:52:31.644 Example:
2025-07-02 04:52:31.644
2025-07-02 04:52:31.644 >>> d = Differ()
2025-07-02 04:52:31.645 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.645 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.645 >>> print(''.join(results), end="")
2025-07-02 04:52:31.645 - abcDefghiJkl
2025-07-02 04:52:31.645 + abcdefGhijkl
2025-07-02 04:52:31.645 """
2025-07-02 04:52:31.645
2025-07-02 04:52:31.645 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.645 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.645 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.645 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.645 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.645
2025-07-02 04:52:31.646 # search for the pair that matches best without being identical
2025-07-02 04:52:31.646 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.646 # on junk -- unless we have to)
2025-07-02 04:52:31.646 for j in range(blo, bhi):
2025-07-02 04:52:31.646 bj = b[j]
2025-07-02 04:52:31.647 cruncher.set_seq2(bj)
2025-07-02 04:52:31.647 for i in range(alo, ahi):
2025-07-02 04:52:31.647 ai = a[i]
2025-07-02 04:52:31.647 if ai == bj:
2025-07-02 04:52:31.647 if eqi is None:
2025-07-02 04:52:31.647 eqi, eqj = i, j
2025-07-02 04:52:31.647 continue
2025-07-02 04:52:31.647 cruncher.set_seq1(ai)
2025-07-02 04:52:31.647 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.647 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.647 # compares by a factor of 3.
2025-07-02 04:52:31.647 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.647 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.647 # of the computation is cached by cruncher
2025-07-02 04:52:31.647 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.647 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.647 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.648 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.648 if best_ratio < cutoff:
2025-07-02 04:52:31.648 # no non-identical "pretty close" pair
2025-07-02 04:52:31.648 if eqi is None:
2025-07-02 04:52:31.648 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.648 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.648 return
2025-07-02 04:52:31.648 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.648 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.648 else:
2025-07-02 04:52:31.648 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.648 eqi = None
2025-07-02 04:52:31.648
2025-07-02 04:52:31.648 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.648 # identical
2025-07-02 04:52:31.648
2025-07-02 04:52:31.648 # pump out diffs from before the synch point
2025-07-02 04:52:31.648 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.648
2025-07-02 04:52:31.648 # do intraline marking on the synch pair
2025-07-02 04:52:31.649 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.649 if eqi is None:
2025-07-02 04:52:31.649 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.649 atags = btags = ""
2025-07-02 04:52:31.649 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.649 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.649 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.649 if tag == 'replace':
2025-07-02 04:52:31.649 atags += '^' * la
2025-07-02 04:52:31.649 btags += '^' * lb
2025-07-02 04:52:31.649 elif tag == 'delete':
2025-07-02 04:52:31.649 atags += '-' * la
2025-07-02 04:52:31.649 elif tag == 'insert':
2025-07-02 04:52:31.649 btags += '+' * lb
2025-07-02 04:52:31.649 elif tag == 'equal':
2025-07-02 04:52:31.649 atags += ' ' * la
2025-07-02 04:52:31.649 btags += ' ' * lb
2025-07-02 04:52:31.649 else:
2025-07-02 04:52:31.649 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.649 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.649 else:
2025-07-02 04:52:31.650 # the synch pair is identical
2025-07-02 04:52:31.650 yield ' ' + aelt
2025-07-02 04:52:31.650
2025-07-02 04:52:31.650 # pump out diffs from after the synch point
2025-07-02 04:52:31.650 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.650
2025-07-02 04:52:31.650 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.650 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.650
2025-07-02 04:52:31.650 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.650 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.650 alo = 82, ahi = 1101
2025-07-02 04:52:31.650 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.650 blo = 82, bhi = 1101
2025-07-02 04:52:31.650
2025-07-02 04:52:31.650 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.650 g = []
2025-07-02 04:52:31.650 if alo < ahi:
2025-07-02 04:52:31.650 if blo < bhi:
2025-07-02 04:52:31.651 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.651 else:
2025-07-02 04:52:31.651 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.651 elif blo < bhi:
2025-07-02 04:52:31.651 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.651
2025-07-02 04:52:31.651 > yield from g
2025-07-02 04:52:31.651
2025-07-02 04:52:31.651 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.651 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.651
2025-07-02 04:52:31.651 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.651 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.651 alo = 82, ahi = 1101
2025-07-02 04:52:31.651 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.651 blo = 82, bhi = 1101
2025-07-02 04:52:31.651
2025-07-02 04:52:31.651 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.651 r"""
2025-07-02 04:52:31.651 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.652 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.652 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.652 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.652
2025-07-02 04:52:31.652 Example:
2025-07-02 04:52:31.652
2025-07-02 04:52:31.652 >>> d = Differ()
2025-07-02 04:52:31.652 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.652 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.652 >>> print(''.join(results), end="")
2025-07-02 04:52:31.652 - abcDefghiJkl
2025-07-02 04:52:31.652 + abcdefGhijkl
2025-07-02 04:52:31.652 """
2025-07-02 04:52:31.652
2025-07-02 04:52:31.652 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.652 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.652 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.652 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.653 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.653
2025-07-02 04:52:31.653 # search for the pair that matches best without being identical
2025-07-02 04:52:31.653 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.653 # on junk -- unless we have to)
2025-07-02 04:52:31.653 for j in range(blo, bhi):
2025-07-02 04:52:31.653 bj = b[j]
2025-07-02 04:52:31.653 cruncher.set_seq2(bj)
2025-07-02 04:52:31.653 for i in range(alo, ahi):
2025-07-02 04:52:31.653 ai = a[i]
2025-07-02 04:52:31.653 if ai == bj:
2025-07-02 04:52:31.653 if eqi is None:
2025-07-02 04:52:31.653 eqi, eqj = i, j
2025-07-02 04:52:31.653 continue
2025-07-02 04:52:31.653 cruncher.set_seq1(ai)
2025-07-02 04:52:31.653 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.653 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.653 # compares by a factor of 3.
2025-07-02 04:52:31.653 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.653 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.654 # of the computation is cached by cruncher
2025-07-02 04:52:31.654 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.654 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.654 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.654 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.654 if best_ratio < cutoff:
2025-07-02 04:52:31.654 # no non-identical "pretty close" pair
2025-07-02 04:52:31.654 if eqi is None:
2025-07-02 04:52:31.654 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.654 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.654 return
2025-07-02 04:52:31.654 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.654 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.654 else:
2025-07-02 04:52:31.654 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.654 eqi = None
2025-07-02 04:52:31.654
2025-07-02 04:52:31.654 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.654 # identical
2025-07-02 04:52:31.654
2025-07-02 04:52:31.655 # pump out diffs from before the synch point
2025-07-02 04:52:31.655 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.655
2025-07-02 04:52:31.655 # do intraline marking on the synch pair
2025-07-02 04:52:31.655 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.655 if eqi is None:
2025-07-02 04:52:31.655 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.655 atags = btags = ""
2025-07-02 04:52:31.655 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.655 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.655 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.655 if tag == 'replace':
2025-07-02 04:52:31.655 atags += '^' * la
2025-07-02 04:52:31.655 btags += '^' * lb
2025-07-02 04:52:31.655 elif tag == 'delete':
2025-07-02 04:52:31.655 atags += '-' * la
2025-07-02 04:52:31.655 elif tag == 'insert':
2025-07-02 04:52:31.655 btags += '+' * lb
2025-07-02 04:52:31.655 elif tag == 'equal':
2025-07-02 04:52:31.655 atags += ' ' * la
2025-07-02 04:52:31.655 btags += ' ' * lb
2025-07-02 04:52:31.656 else:
2025-07-02 04:52:31.656 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.656 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.656 else:
2025-07-02 04:52:31.656 # the synch pair is identical
2025-07-02 04:52:31.656 yield ' ' + aelt
2025-07-02 04:52:31.656
2025-07-02 04:52:31.656 # pump out diffs from after the synch point
2025-07-02 04:52:31.656 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.656
2025-07-02 04:52:31.656 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.656 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.656
2025-07-02 04:52:31.656 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.656 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.656 alo = 83, ahi = 1101
2025-07-02 04:52:31.656 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.656 blo = 83, bhi = 1101
2025-07-02 04:52:31.656
2025-07-02 04:52:31.656 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.657 g = []
2025-07-02 04:52:31.657 if alo < ahi:
2025-07-02 04:52:31.657 if blo < bhi:
2025-07-02 04:52:31.657 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.657 else:
2025-07-02 04:52:31.657 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.657 elif blo < bhi:
2025-07-02 04:52:31.657 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.657
2025-07-02 04:52:31.657 > yield from g
2025-07-02 04:52:31.657
2025-07-02 04:52:31.657 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.657 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.657
2025-07-02 04:52:31.657 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.657 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.657 alo = 83, ahi = 1101
2025-07-02 04:52:31.657 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.657 blo = 83, bhi = 1101
2025-07-02 04:52:31.657
2025-07-02 04:52:31.657 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.658 r"""
2025-07-02 04:52:31.658 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.658 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.658 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.658 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.658
2025-07-02 04:52:31.658 Example:
2025-07-02 04:52:31.658
2025-07-02 04:52:31.658 >>> d = Differ()
2025-07-02 04:52:31.658 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.658 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.658 >>> print(''.join(results), end="")
2025-07-02 04:52:31.658 - abcDefghiJkl
2025-07-02 04:52:31.658 + abcdefGhijkl
2025-07-02 04:52:31.658 """
2025-07-02 04:52:31.658
2025-07-02 04:52:31.658 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.658 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.659 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.659 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.659 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.659
2025-07-02 04:52:31.659 # search for the pair that matches best without being identical
2025-07-02 04:52:31.659 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.659 # on junk -- unless we have to)
2025-07-02 04:52:31.659 for j in range(blo, bhi):
2025-07-02 04:52:31.659 bj = b[j]
2025-07-02 04:52:31.659 cruncher.set_seq2(bj)
2025-07-02 04:52:31.659 for i in range(alo, ahi):
2025-07-02 04:52:31.659 ai = a[i]
2025-07-02 04:52:31.659 if ai == bj:
2025-07-02 04:52:31.659 if eqi is None:
2025-07-02 04:52:31.659 eqi, eqj = i, j
2025-07-02 04:52:31.659 continue
2025-07-02 04:52:31.659 cruncher.set_seq1(ai)
2025-07-02 04:52:31.659 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.660 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.660 # compares by a factor of 3.
2025-07-02 04:52:31.660 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.660 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.660 # of the computation is cached by cruncher
2025-07-02 04:52:31.660 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.660 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.660 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.660 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.660 if best_ratio < cutoff:
2025-07-02 04:52:31.660 # no non-identical "pretty close" pair
2025-07-02 04:52:31.660 if eqi is None:
2025-07-02 04:52:31.660 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.660 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.660 return
2025-07-02 04:52:31.660 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.660 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.660 else:
2025-07-02 04:52:31.660 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.660 eqi = None
2025-07-02 04:52:31.661
2025-07-02 04:52:31.661 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.661 # identical
2025-07-02 04:52:31.661
2025-07-02 04:52:31.661 # pump out diffs from before the synch point
2025-07-02 04:52:31.661 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.661
2025-07-02 04:52:31.661 # do intraline marking on the synch pair
2025-07-02 04:52:31.661 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.661 if eqi is None:
2025-07-02 04:52:31.661 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.661 atags = btags = ""
2025-07-02 04:52:31.661 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.661 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.661 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.661 if tag == 'replace':
2025-07-02 04:52:31.661 atags += '^' * la
2025-07-02 04:52:31.661 btags += '^' * lb
2025-07-02 04:52:31.661 elif tag == 'delete':
2025-07-02 04:52:31.661 atags += '-' * la
2025-07-02 04:52:31.661 elif tag == 'insert':
2025-07-02 04:52:31.662 btags += '+' * lb
2025-07-02 04:52:31.662 elif tag == 'equal':
2025-07-02 04:52:31.662 atags += ' ' * la
2025-07-02 04:52:31.662 btags += ' ' * lb
2025-07-02 04:52:31.662 else:
2025-07-02 04:52:31.662 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.662 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.662 else:
2025-07-02 04:52:31.662 # the synch pair is identical
2025-07-02 04:52:31.662 yield ' ' + aelt
2025-07-02 04:52:31.662
2025-07-02 04:52:31.662 # pump out diffs from after the synch point
2025-07-02 04:52:31.662 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.662
2025-07-02 04:52:31.662 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.662 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.662
2025-07-02 04:52:31.662 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.662 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.662 alo = 84, ahi = 1101
2025-07-02 04:52:31.662 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.663 blo = 84, bhi = 1101
2025-07-02 04:52:31.663
2025-07-02 04:52:31.663 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.663 g = []
2025-07-02 04:52:31.663 if alo < ahi:
2025-07-02 04:52:31.663 if blo < bhi:
2025-07-02 04:52:31.663 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.663 else:
2025-07-02 04:52:31.663 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.663 elif blo < bhi:
2025-07-02 04:52:31.663 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.663
2025-07-02 04:52:31.663 > yield from g
2025-07-02 04:52:31.663
2025-07-02 04:52:31.663 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.663 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.663
2025-07-02 04:52:31.663 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.663 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.663 alo = 84, ahi = 1101
2025-07-02 04:52:31.663 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.663 blo = 84, bhi = 1101
2025-07-02 04:52:31.664
2025-07-02 04:52:31.664 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.664 r"""
2025-07-02 04:52:31.664 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.664 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.664 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.664 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.664
2025-07-02 04:52:31.664 Example:
2025-07-02 04:52:31.664
2025-07-02 04:52:31.664 >>> d = Differ()
2025-07-02 04:52:31.664 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.664 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.664 >>> print(''.join(results), end="")
2025-07-02 04:52:31.664 - abcDefghiJkl
2025-07-02 04:52:31.664 + abcdefGhijkl
2025-07-02 04:52:31.664 """
2025-07-02 04:52:31.664
2025-07-02 04:52:31.664 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.665 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.665 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.665 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.665 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.665
2025-07-02 04:52:31.665 # search for the pair that matches best without being identical
2025-07-02 04:52:31.665 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.665 # on junk -- unless we have to)
2025-07-02 04:52:31.665 for j in range(blo, bhi):
2025-07-02 04:52:31.665 bj = b[j]
2025-07-02 04:52:31.665 cruncher.set_seq2(bj)
2025-07-02 04:52:31.665 for i in range(alo, ahi):
2025-07-02 04:52:31.665 ai = a[i]
2025-07-02 04:52:31.665 if ai == bj:
2025-07-02 04:52:31.665 if eqi is None:
2025-07-02 04:52:31.665 eqi, eqj = i, j
2025-07-02 04:52:31.665 continue
2025-07-02 04:52:31.665 cruncher.set_seq1(ai)
2025-07-02 04:52:31.665 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.665 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.665 # compares by a factor of 3.
2025-07-02 04:52:31.665 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.666 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.666 # of the computation is cached by cruncher
2025-07-02 04:52:31.666 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.666 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.666 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.666 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.666 if best_ratio < cutoff:
2025-07-02 04:52:31.666 # no non-identical "pretty close" pair
2025-07-02 04:52:31.666 if eqi is None:
2025-07-02 04:52:31.666 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.666 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.666 return
2025-07-02 04:52:31.666 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.666 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.666 else:
2025-07-02 04:52:31.666 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.666 eqi = None
2025-07-02 04:52:31.666
2025-07-02 04:52:31.666 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.666 # identical
2025-07-02 04:52:31.666
2025-07-02 04:52:31.667 # pump out diffs from before the synch point
2025-07-02 04:52:31.667 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.667
2025-07-02 04:52:31.667 # do intraline marking on the synch pair
2025-07-02 04:52:31.667 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.667 if eqi is None:
2025-07-02 04:52:31.667 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.667 atags = btags = ""
2025-07-02 04:52:31.667 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.667 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.667 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.667 if tag == 'replace':
2025-07-02 04:52:31.667 atags += '^' * la
2025-07-02 04:52:31.667 btags += '^' * lb
2025-07-02 04:52:31.667 elif tag == 'delete':
2025-07-02 04:52:31.667 atags += '-' * la
2025-07-02 04:52:31.667 elif tag == 'insert':
2025-07-02 04:52:31.667 btags += '+' * lb
2025-07-02 04:52:31.667 elif tag == 'equal':
2025-07-02 04:52:31.667 atags += ' ' * la
2025-07-02 04:52:31.668 btags += ' ' * lb
2025-07-02 04:52:31.668 else:
2025-07-02 04:52:31.668 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.668 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.668 else:
2025-07-02 04:52:31.668 # the synch pair is identical
2025-07-02 04:52:31.668 yield ' ' + aelt
2025-07-02 04:52:31.668
2025-07-02 04:52:31.668 # pump out diffs from after the synch point
2025-07-02 04:52:31.668 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.668
2025-07-02 04:52:31.668 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.668 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.668
2025-07-02 04:52:31.668 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.668 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.668 alo = 85, ahi = 1101
2025-07-02 04:52:31.668 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.668 blo = 85, bhi = 1101
2025-07-02 04:52:31.668
2025-07-02 04:52:31.669 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.669 g = []
2025-07-02 04:52:31.669 if alo < ahi:
2025-07-02 04:52:31.669 if blo < bhi:
2025-07-02 04:52:31.669 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.669 else:
2025-07-02 04:52:31.669 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.669 elif blo < bhi:
2025-07-02 04:52:31.669 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.669
2025-07-02 04:52:31.669 > yield from g
2025-07-02 04:52:31.669
2025-07-02 04:52:31.669 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.669 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.669
2025-07-02 04:52:31.669 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.669 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.669 alo = 85, ahi = 1101
2025-07-02 04:52:31.669 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.669 blo = 85, bhi = 1101
2025-07-02 04:52:31.669
2025-07-02 04:52:31.670 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.670 r"""
2025-07-02 04:52:31.670 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.670 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.670 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.670 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.670
2025-07-02 04:52:31.670 Example:
2025-07-02 04:52:31.670
2025-07-02 04:52:31.670 >>> d = Differ()
2025-07-02 04:52:31.670 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.670 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.670 >>> print(''.join(results), end="")
2025-07-02 04:52:31.670 - abcDefghiJkl
2025-07-02 04:52:31.670 + abcdefGhijkl
2025-07-02 04:52:31.670 """
2025-07-02 04:52:31.670
2025-07-02 04:52:31.670 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.670 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.671 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.671 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.671 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.671
2025-07-02 04:52:31.671 # search for the pair that matches best without being identical
2025-07-02 04:52:31.671 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.671 # on junk -- unless we have to)
2025-07-02 04:52:31.671 for j in range(blo, bhi):
2025-07-02 04:52:31.671 bj = b[j]
2025-07-02 04:52:31.671 cruncher.set_seq2(bj)
2025-07-02 04:52:31.671 for i in range(alo, ahi):
2025-07-02 04:52:31.671 ai = a[i]
2025-07-02 04:52:31.671 if ai == bj:
2025-07-02 04:52:31.671 if eqi is None:
2025-07-02 04:52:31.671 eqi, eqj = i, j
2025-07-02 04:52:31.671 continue
2025-07-02 04:52:31.671 cruncher.set_seq1(ai)
2025-07-02 04:52:31.671 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.671 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.671 # compares by a factor of 3.
2025-07-02 04:52:31.671 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.671 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.672 # of the computation is cached by cruncher
2025-07-02 04:52:31.672 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.672 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.672 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.672 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.672 if best_ratio < cutoff:
2025-07-02 04:52:31.672 # no non-identical "pretty close" pair
2025-07-02 04:52:31.672 if eqi is None:
2025-07-02 04:52:31.672 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.672 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.672 return
2025-07-02 04:52:31.672 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.672 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.672 else:
2025-07-02 04:52:31.672 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.672 eqi = None
2025-07-02 04:52:31.672
2025-07-02 04:52:31.672 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.672 # identical
2025-07-02 04:52:31.672
2025-07-02 04:52:31.672 # pump out diffs from before the synch point
2025-07-02 04:52:31.673 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.673
2025-07-02 04:52:31.673 # do intraline marking on the synch pair
2025-07-02 04:52:31.673 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.673 if eqi is None:
2025-07-02 04:52:31.673 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.673 atags = btags = ""
2025-07-02 04:52:31.673 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.673 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.673 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.673 if tag == 'replace':
2025-07-02 04:52:31.673 atags += '^' * la
2025-07-02 04:52:31.673 btags += '^' * lb
2025-07-02 04:52:31.673 elif tag == 'delete':
2025-07-02 04:52:31.673 atags += '-' * la
2025-07-02 04:52:31.673 elif tag == 'insert':
2025-07-02 04:52:31.673 btags += '+' * lb
2025-07-02 04:52:31.673 elif tag == 'equal':
2025-07-02 04:52:31.673 atags += ' ' * la
2025-07-02 04:52:31.673 btags += ' ' * lb
2025-07-02 04:52:31.673 else:
2025-07-02 04:52:31.673 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.674 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.674 else:
2025-07-02 04:52:31.674 # the synch pair is identical
2025-07-02 04:52:31.674 yield ' ' + aelt
2025-07-02 04:52:31.674
2025-07-02 04:52:31.674 # pump out diffs from after the synch point
2025-07-02 04:52:31.674 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.674
2025-07-02 04:52:31.674 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.674 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.674
2025-07-02 04:52:31.674 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.674 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.674 alo = 86, ahi = 1101
2025-07-02 04:52:31.674 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.674 blo = 86, bhi = 1101
2025-07-02 04:52:31.674
2025-07-02 04:52:31.674 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.674 g = []
2025-07-02 04:52:31.674 if alo < ahi:
2025-07-02 04:52:31.674 if blo < bhi:
2025-07-02 04:52:31.675 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.675 else:
2025-07-02 04:52:31.675 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.675 elif blo < bhi:
2025-07-02 04:52:31.675 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.675
2025-07-02 04:52:31.675 > yield from g
2025-07-02 04:52:31.675
2025-07-02 04:52:31.675 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.675 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.675
2025-07-02 04:52:31.675 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.675 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.675 alo = 86, ahi = 1101
2025-07-02 04:52:31.675 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.675 blo = 86, bhi = 1101
2025-07-02 04:52:31.675
2025-07-02 04:52:31.675 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.675 r"""
2025-07-02 04:52:31.676 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.676 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.676 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.676 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.676
2025-07-02 04:52:31.676 Example:
2025-07-02 04:52:31.676
2025-07-02 04:52:31.676 >>> d = Differ()
2025-07-02 04:52:31.676 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.676 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.676 >>> print(''.join(results), end="")
2025-07-02 04:52:31.676 - abcDefghiJkl
2025-07-02 04:52:31.676 + abcdefGhijkl
2025-07-02 04:52:31.676 """
2025-07-02 04:52:31.676
2025-07-02 04:52:31.676 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.676 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.677 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.677 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.677 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.677
2025-07-02 04:52:31.677 # search for the pair that matches best without being identical
2025-07-02 04:52:31.677 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.677 # on junk -- unless we have to)
2025-07-02 04:52:31.677 for j in range(blo, bhi):
2025-07-02 04:52:31.677 bj = b[j]
2025-07-02 04:52:31.677 cruncher.set_seq2(bj)
2025-07-02 04:52:31.677 for i in range(alo, ahi):
2025-07-02 04:52:31.677 ai = a[i]
2025-07-02 04:52:31.677 if ai == bj:
2025-07-02 04:52:31.677 if eqi is None:
2025-07-02 04:52:31.677 eqi, eqj = i, j
2025-07-02 04:52:31.677 continue
2025-07-02 04:52:31.677 cruncher.set_seq1(ai)
2025-07-02 04:52:31.677 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.677 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.677 # compares by a factor of 3.
2025-07-02 04:52:31.678 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.678 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.678 # of the computation is cached by cruncher
2025-07-02 04:52:31.678 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.678 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.678 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.678 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.678 if best_ratio < cutoff:
2025-07-02 04:52:31.678 # no non-identical "pretty close" pair
2025-07-02 04:52:31.678 if eqi is None:
2025-07-02 04:52:31.678 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.678 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.678 return
2025-07-02 04:52:31.678 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.678 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.678 else:
2025-07-02 04:52:31.678 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.678 eqi = None
2025-07-02 04:52:31.678
2025-07-02 04:52:31.678 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.679 # identical
2025-07-02 04:52:31.679
2025-07-02 04:52:31.679 # pump out diffs from before the synch point
2025-07-02 04:52:31.679 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.679
2025-07-02 04:52:31.679 # do intraline marking on the synch pair
2025-07-02 04:52:31.679 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.679 if eqi is None:
2025-07-02 04:52:31.679 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.679 atags = btags = ""
2025-07-02 04:52:31.679 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.679 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.679 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.679 if tag == 'replace':
2025-07-02 04:52:31.679 atags += '^' * la
2025-07-02 04:52:31.679 btags += '^' * lb
2025-07-02 04:52:31.679 elif tag == 'delete':
2025-07-02 04:52:31.679 atags += '-' * la
2025-07-02 04:52:31.679 elif tag == 'insert':
2025-07-02 04:52:31.679 btags += '+' * lb
2025-07-02 04:52:31.679 elif tag == 'equal':
2025-07-02 04:52:31.679 atags += ' ' * la
2025-07-02 04:52:31.680 btags += ' ' * lb
2025-07-02 04:52:31.680 else:
2025-07-02 04:52:31.680 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.680 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.680 else:
2025-07-02 04:52:31.680 # the synch pair is identical
2025-07-02 04:52:31.680 yield ' ' + aelt
2025-07-02 04:52:31.680
2025-07-02 04:52:31.680 # pump out diffs from after the synch point
2025-07-02 04:52:31.680 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.680
2025-07-02 04:52:31.680 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.680 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.680
2025-07-02 04:52:31.680 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.680 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.680 alo = 87, ahi = 1101
2025-07-02 04:52:31.680 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.680 blo = 87, bhi = 1101
2025-07-02 04:52:31.680
2025-07-02 04:52:31.680 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.681 g = []
2025-07-02 04:52:31.681 if alo < ahi:
2025-07-02 04:52:31.681 if blo < bhi:
2025-07-02 04:52:31.681 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.681 else:
2025-07-02 04:52:31.681 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.681 elif blo < bhi:
2025-07-02 04:52:31.681 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.681
2025-07-02 04:52:31.681 > yield from g
2025-07-02 04:52:31.681
2025-07-02 04:52:31.681 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.681 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.681
2025-07-02 04:52:31.681 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.681 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.681 alo = 87, ahi = 1101
2025-07-02 04:52:31.681 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.681 blo = 87, bhi = 1101
2025-07-02 04:52:31.681
2025-07-02 04:52:31.681 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.681 r"""
2025-07-02 04:52:31.682 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.682 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.682 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.682 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.682
2025-07-02 04:52:31.682 Example:
2025-07-02 04:52:31.682
2025-07-02 04:52:31.682 >>> d = Differ()
2025-07-02 04:52:31.682 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.682 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.682 >>> print(''.join(results), end="")
2025-07-02 04:52:31.682 - abcDefghiJkl
2025-07-02 04:52:31.682 + abcdefGhijkl
2025-07-02 04:52:31.682 """
2025-07-02 04:52:31.682
2025-07-02 04:52:31.682 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.682 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.682 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.682 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.683 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.683
2025-07-02 04:52:31.683 # search for the pair that matches best without being identical
2025-07-02 04:52:31.683 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.683 # on junk -- unless we have to)
2025-07-02 04:52:31.683 for j in range(blo, bhi):
2025-07-02 04:52:31.683 bj = b[j]
2025-07-02 04:52:31.683 cruncher.set_seq2(bj)
2025-07-02 04:52:31.683 for i in range(alo, ahi):
2025-07-02 04:52:31.683 ai = a[i]
2025-07-02 04:52:31.683 if ai == bj:
2025-07-02 04:52:31.683 if eqi is None:
2025-07-02 04:52:31.683 eqi, eqj = i, j
2025-07-02 04:52:31.683 continue
2025-07-02 04:52:31.683 cruncher.set_seq1(ai)
2025-07-02 04:52:31.683 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.683 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.683 # compares by a factor of 3.
2025-07-02 04:52:31.683 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.683 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.684 # of the computation is cached by cruncher
2025-07-02 04:52:31.684 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.684 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.684 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.684 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.684 if best_ratio < cutoff:
2025-07-02 04:52:31.684 # no non-identical "pretty close" pair
2025-07-02 04:52:31.684 if eqi is None:
2025-07-02 04:52:31.684 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.684 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.684 return
2025-07-02 04:52:31.684 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.684 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.684 else:
2025-07-02 04:52:31.684 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.684 eqi = None
2025-07-02 04:52:31.684
2025-07-02 04:52:31.684 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.684 # identical
2025-07-02 04:52:31.684
2025-07-02 04:52:31.685 # pump out diffs from before the synch point
2025-07-02 04:52:31.685 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.685
2025-07-02 04:52:31.685 # do intraline marking on the synch pair
2025-07-02 04:52:31.685 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.685 if eqi is None:
2025-07-02 04:52:31.685 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.685 atags = btags = ""
2025-07-02 04:52:31.685 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.685 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.685 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.685 if tag == 'replace':
2025-07-02 04:52:31.685 atags += '^' * la
2025-07-02 04:52:31.685 btags += '^' * lb
2025-07-02 04:52:31.685 elif tag == 'delete':
2025-07-02 04:52:31.685 atags += '-' * la
2025-07-02 04:52:31.685 elif tag == 'insert':
2025-07-02 04:52:31.685 btags += '+' * lb
2025-07-02 04:52:31.685 elif tag == 'equal':
2025-07-02 04:52:31.685 atags += ' ' * la
2025-07-02 04:52:31.685 btags += ' ' * lb
2025-07-02 04:52:31.686 else:
2025-07-02 04:52:31.686 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.686 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.686 else:
2025-07-02 04:52:31.686 # the synch pair is identical
2025-07-02 04:52:31.686 yield ' ' + aelt
2025-07-02 04:52:31.686
2025-07-02 04:52:31.686 # pump out diffs from after the synch point
2025-07-02 04:52:31.686 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.686
2025-07-02 04:52:31.686 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.686 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.686
2025-07-02 04:52:31.686 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.686 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.686 alo = 88, ahi = 1101
2025-07-02 04:52:31.686 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.686 blo = 88, bhi = 1101
2025-07-02 04:52:31.686
2025-07-02 04:52:31.686 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.687 g = []
2025-07-02 04:52:31.687 if alo < ahi:
2025-07-02 04:52:31.687 if blo < bhi:
2025-07-02 04:52:31.687 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.687 else:
2025-07-02 04:52:31.687 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.687 elif blo < bhi:
2025-07-02 04:52:31.687 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.687
2025-07-02 04:52:31.687 > yield from g
2025-07-02 04:52:31.687
2025-07-02 04:52:31.687 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.687 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.687
2025-07-02 04:52:31.687 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.687 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.687 alo = 88, ahi = 1101
2025-07-02 04:52:31.687 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.687 blo = 88, bhi = 1101
2025-07-02 04:52:31.687
2025-07-02 04:52:31.688 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.688 r"""
2025-07-02 04:52:31.688 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.688 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.688 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.688 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.688
2025-07-02 04:52:31.688 Example:
2025-07-02 04:52:31.688
2025-07-02 04:52:31.688 >>> d = Differ()
2025-07-02 04:52:31.688 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.688 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.688 >>> print(''.join(results), end="")
2025-07-02 04:52:31.688 - abcDefghiJkl
2025-07-02 04:52:31.688 + abcdefGhijkl
2025-07-02 04:52:31.688 """
2025-07-02 04:52:31.688
2025-07-02 04:52:31.688 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.688 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.689 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.689 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.689 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.689
2025-07-02 04:52:31.689 # search for the pair that matches best without being identical
2025-07-02 04:52:31.689 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.689 # on junk -- unless we have to)
2025-07-02 04:52:31.689 for j in range(blo, bhi):
2025-07-02 04:52:31.689 bj = b[j]
2025-07-02 04:52:31.689 cruncher.set_seq2(bj)
2025-07-02 04:52:31.689 for i in range(alo, ahi):
2025-07-02 04:52:31.689 ai = a[i]
2025-07-02 04:52:31.689 if ai == bj:
2025-07-02 04:52:31.689 if eqi is None:
2025-07-02 04:52:31.689 eqi, eqj = i, j
2025-07-02 04:52:31.689 continue
2025-07-02 04:52:31.689 cruncher.set_seq1(ai)
2025-07-02 04:52:31.689 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.689 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.689 # compares by a factor of 3.
2025-07-02 04:52:31.690 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.690 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.690 # of the computation is cached by cruncher
2025-07-02 04:52:31.690 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.690 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.690 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.690 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.690 if best_ratio < cutoff:
2025-07-02 04:52:31.690 # no non-identical "pretty close" pair
2025-07-02 04:52:31.690 if eqi is None:
2025-07-02 04:52:31.690 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.690 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.690 return
2025-07-02 04:52:31.690 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.690 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.690 else:
2025-07-02 04:52:31.690 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.690 eqi = None
2025-07-02 04:52:31.690
2025-07-02 04:52:31.690 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.690 # identical
2025-07-02 04:52:31.691
2025-07-02 04:52:31.691 # pump out diffs from before the synch point
2025-07-02 04:52:31.691 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.691
2025-07-02 04:52:31.691 # do intraline marking on the synch pair
2025-07-02 04:52:31.691 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.691 if eqi is None:
2025-07-02 04:52:31.691 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.691 atags = btags = ""
2025-07-02 04:52:31.691 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.691 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.691 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.691 if tag == 'replace':
2025-07-02 04:52:31.691 atags += '^' * la
2025-07-02 04:52:31.691 btags += '^' * lb
2025-07-02 04:52:31.691 elif tag == 'delete':
2025-07-02 04:52:31.691 atags += '-' * la
2025-07-02 04:52:31.691 elif tag == 'insert':
2025-07-02 04:52:31.691 btags += '+' * lb
2025-07-02 04:52:31.691 elif tag == 'equal':
2025-07-02 04:52:31.691 atags += ' ' * la
2025-07-02 04:52:31.692 btags += ' ' * lb
2025-07-02 04:52:31.692 else:
2025-07-02 04:52:31.692 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.692 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.692 else:
2025-07-02 04:52:31.692 # the synch pair is identical
2025-07-02 04:52:31.692 yield ' ' + aelt
2025-07-02 04:52:31.692
2025-07-02 04:52:31.692 # pump out diffs from after the synch point
2025-07-02 04:52:31.692 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.692
2025-07-02 04:52:31.692 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.692 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.692
2025-07-02 04:52:31.692 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.692 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.692 alo = 89, ahi = 1101
2025-07-02 04:52:31.692 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.693 blo = 89, bhi = 1101
2025-07-02 04:52:31.693
2025-07-02 04:52:31.693 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.693 g = []
2025-07-02 04:52:31.693 if alo < ahi:
2025-07-02 04:52:31.693 if blo < bhi:
2025-07-02 04:52:31.693 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.693 else:
2025-07-02 04:52:31.693 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.693 elif blo < bhi:
2025-07-02 04:52:31.693 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.693
2025-07-02 04:52:31.693 > yield from g
2025-07-02 04:52:31.693
2025-07-02 04:52:31.693 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.693 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.693
2025-07-02 04:52:31.693 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.693 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.693 alo = 89, ahi = 1101
2025-07-02 04:52:31.693 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.694 blo = 89, bhi = 1101
2025-07-02 04:52:31.694
2025-07-02 04:52:31.694 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.694 r"""
2025-07-02 04:52:31.694 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.694 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.694 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.694 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.694
2025-07-02 04:52:31.694 Example:
2025-07-02 04:52:31.694
2025-07-02 04:52:31.694 >>> d = Differ()
2025-07-02 04:52:31.694 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.694 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.694 >>> print(''.join(results), end="")
2025-07-02 04:52:31.694 - abcDefghiJkl
2025-07-02 04:52:31.694 + abcdefGhijkl
2025-07-02 04:52:31.694 """
2025-07-02 04:52:31.695
2025-07-02 04:52:31.695 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.695 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.695 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.695 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.695 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.695
2025-07-02 04:52:31.695 # search for the pair that matches best without being identical
2025-07-02 04:52:31.695 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.695 # on junk -- unless we have to)
2025-07-02 04:52:31.695 for j in range(blo, bhi):
2025-07-02 04:52:31.695 bj = b[j]
2025-07-02 04:52:31.695 cruncher.set_seq2(bj)
2025-07-02 04:52:31.695 for i in range(alo, ahi):
2025-07-02 04:52:31.695 ai = a[i]
2025-07-02 04:52:31.695 if ai == bj:
2025-07-02 04:52:31.695 if eqi is None:
2025-07-02 04:52:31.695 eqi, eqj = i, j
2025-07-02 04:52:31.695 continue
2025-07-02 04:52:31.695 cruncher.set_seq1(ai)
2025-07-02 04:52:31.695 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.696 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.696 # compares by a factor of 3.
2025-07-02 04:52:31.696 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.696 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.696 # of the computation is cached by cruncher
2025-07-02 04:52:31.696 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.696 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.696 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.696 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.696 if best_ratio < cutoff:
2025-07-02 04:52:31.696 # no non-identical "pretty close" pair
2025-07-02 04:52:31.696 if eqi is None:
2025-07-02 04:52:31.696 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.696 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.696 return
2025-07-02 04:52:31.696 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.696 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.696 else:
2025-07-02 04:52:31.696 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.696 eqi = None
2025-07-02 04:52:31.697
2025-07-02 04:52:31.697 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.697 # identical
2025-07-02 04:52:31.697
2025-07-02 04:52:31.697 # pump out diffs from before the synch point
2025-07-02 04:52:31.697 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.697
2025-07-02 04:52:31.697 # do intraline marking on the synch pair
2025-07-02 04:52:31.697 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.697 if eqi is None:
2025-07-02 04:52:31.697 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.697 atags = btags = ""
2025-07-02 04:52:31.697 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.697 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.697 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.697 if tag == 'replace':
2025-07-02 04:52:31.697 atags += '^' * la
2025-07-02 04:52:31.697 btags += '^' * lb
2025-07-02 04:52:31.697 elif tag == 'delete':
2025-07-02 04:52:31.697 atags += '-' * la
2025-07-02 04:52:31.697 elif tag == 'insert':
2025-07-02 04:52:31.698 btags += '+' * lb
2025-07-02 04:52:31.698 elif tag == 'equal':
2025-07-02 04:52:31.698 atags += ' ' * la
2025-07-02 04:52:31.698 btags += ' ' * lb
2025-07-02 04:52:31.698 else:
2025-07-02 04:52:31.698 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.698 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.698 else:
2025-07-02 04:52:31.698 # the synch pair is identical
2025-07-02 04:52:31.698 yield ' ' + aelt
2025-07-02 04:52:31.698
2025-07-02 04:52:31.698 # pump out diffs from after the synch point
2025-07-02 04:52:31.698 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.698
2025-07-02 04:52:31.698 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.698 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.698
2025-07-02 04:52:31.698 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.698 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.698 alo = 92, ahi = 1101
2025-07-02 04:52:31.699 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.699 blo = 92, bhi = 1101
2025-07-02 04:52:31.699
2025-07-02 04:52:31.699 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.699 g = []
2025-07-02 04:52:31.699 if alo < ahi:
2025-07-02 04:52:31.699 if blo < bhi:
2025-07-02 04:52:31.699 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.699 else:
2025-07-02 04:52:31.699 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.699 elif blo < bhi:
2025-07-02 04:52:31.699 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.699
2025-07-02 04:52:31.699 > yield from g
2025-07-02 04:52:31.699
2025-07-02 04:52:31.699 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.699 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.699
2025-07-02 04:52:31.699 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.699 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.699 alo = 92, ahi = 1101
2025-07-02 04:52:31.700 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.700 blo = 92, bhi = 1101
2025-07-02 04:52:31.700
2025-07-02 04:52:31.700 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.700 r"""
2025-07-02 04:52:31.700 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.700 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.700 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.700 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.700
2025-07-02 04:52:31.700 Example:
2025-07-02 04:52:31.700
2025-07-02 04:52:31.700 >>> d = Differ()
2025-07-02 04:52:31.700 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.700 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.700 >>> print(''.join(results), end="")
2025-07-02 04:52:31.700 - abcDefghiJkl
2025-07-02 04:52:31.700 + abcdefGhijkl
2025-07-02 04:52:31.701 """
2025-07-02 04:52:31.701
2025-07-02 04:52:31.701 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.701 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.701 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.701 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.701 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.701
2025-07-02 04:52:31.701 # search for the pair that matches best without being identical
2025-07-02 04:52:31.701 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.701 # on junk -- unless we have to)
2025-07-02 04:52:31.701 for j in range(blo, bhi):
2025-07-02 04:52:31.701 bj = b[j]
2025-07-02 04:52:31.701 cruncher.set_seq2(bj)
2025-07-02 04:52:31.701 for i in range(alo, ahi):
2025-07-02 04:52:31.701 ai = a[i]
2025-07-02 04:52:31.701 if ai == bj:
2025-07-02 04:52:31.701 if eqi is None:
2025-07-02 04:52:31.701 eqi, eqj = i, j
2025-07-02 04:52:31.702 continue
2025-07-02 04:52:31.702 cruncher.set_seq1(ai)
2025-07-02 04:52:31.702 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.702 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.702 # compares by a factor of 3.
2025-07-02 04:52:31.702 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.702 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.702 # of the computation is cached by cruncher
2025-07-02 04:52:31.702 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.702 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.702 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.702 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.702 if best_ratio < cutoff:
2025-07-02 04:52:31.702 # no non-identical "pretty close" pair
2025-07-02 04:52:31.702 if eqi is None:
2025-07-02 04:52:31.702 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.702 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.702 return
2025-07-02 04:52:31.702 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.702 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.702 else:
2025-07-02 04:52:31.703 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.703 eqi = None
2025-07-02 04:52:31.703
2025-07-02 04:52:31.703 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.703 # identical
2025-07-02 04:52:31.703
2025-07-02 04:52:31.703 # pump out diffs from before the synch point
2025-07-02 04:52:31.703 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.703
2025-07-02 04:52:31.703 # do intraline marking on the synch pair
2025-07-02 04:52:31.703 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.703 if eqi is None:
2025-07-02 04:52:31.703 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.703 atags = btags = ""
2025-07-02 04:52:31.703 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.703 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.703 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.703 if tag == 'replace':
2025-07-02 04:52:31.703 atags += '^' * la
2025-07-02 04:52:31.703 btags += '^' * lb
2025-07-02 04:52:31.704 elif tag == 'delete':
2025-07-02 04:52:31.704 atags += '-' * la
2025-07-02 04:52:31.704 elif tag == 'insert':
2025-07-02 04:52:31.704 btags += '+' * lb
2025-07-02 04:52:31.704 elif tag == 'equal':
2025-07-02 04:52:31.704 atags += ' ' * la
2025-07-02 04:52:31.704 btags += ' ' * lb
2025-07-02 04:52:31.704 else:
2025-07-02 04:52:31.704 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.704 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.704 else:
2025-07-02 04:52:31.704 # the synch pair is identical
2025-07-02 04:52:31.704 yield ' ' + aelt
2025-07-02 04:52:31.704
2025-07-02 04:52:31.704 # pump out diffs from after the synch point
2025-07-02 04:52:31.704 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.704
2025-07-02 04:52:31.704 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.704 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.704
2025-07-02 04:52:31.704 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.705 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.705 alo = 93, ahi = 1101
2025-07-02 04:52:31.705 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.705 blo = 93, bhi = 1101
2025-07-02 04:52:31.705
2025-07-02 04:52:31.705 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.705 g = []
2025-07-02 04:52:31.705 if alo < ahi:
2025-07-02 04:52:31.705 if blo < bhi:
2025-07-02 04:52:31.705 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.705 else:
2025-07-02 04:52:31.705 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.705 elif blo < bhi:
2025-07-02 04:52:31.705 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.705
2025-07-02 04:52:31.705 > yield from g
2025-07-02 04:52:31.705
2025-07-02 04:52:31.705 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.705 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.705
2025-07-02 04:52:31.705 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.706 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.706 alo = 93, ahi = 1101
2025-07-02 04:52:31.706 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.706 blo = 93, bhi = 1101
2025-07-02 04:52:31.706
2025-07-02 04:52:31.706 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.706 r"""
2025-07-02 04:52:31.706 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.706 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.706 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.706 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.706
2025-07-02 04:52:31.706 Example:
2025-07-02 04:52:31.706
2025-07-02 04:52:31.706 >>> d = Differ()
2025-07-02 04:52:31.706 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.706 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.706 >>> print(''.join(results), end="")
2025-07-02 04:52:31.706 - abcDefghiJkl
2025-07-02 04:52:31.707 + abcdefGhijkl
2025-07-02 04:52:31.707 """
2025-07-02 04:52:31.707
2025-07-02 04:52:31.707 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.707 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.707 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.707 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.707 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.707
2025-07-02 04:52:31.707 # search for the pair that matches best without being identical
2025-07-02 04:52:31.707 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.707 # on junk -- unless we have to)
2025-07-02 04:52:31.707 for j in range(blo, bhi):
2025-07-02 04:52:31.707 bj = b[j]
2025-07-02 04:52:31.707 cruncher.set_seq2(bj)
2025-07-02 04:52:31.707 for i in range(alo, ahi):
2025-07-02 04:52:31.707 ai = a[i]
2025-07-02 04:52:31.707 if ai == bj:
2025-07-02 04:52:31.707 if eqi is None:
2025-07-02 04:52:31.707 eqi, eqj = i, j
2025-07-02 04:52:31.708 continue
2025-07-02 04:52:31.708 cruncher.set_seq1(ai)
2025-07-02 04:52:31.708 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.708 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.708 # compares by a factor of 3.
2025-07-02 04:52:31.708 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.708 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.708 # of the computation is cached by cruncher
2025-07-02 04:52:31.708 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.708 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.708 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.708 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.708 if best_ratio < cutoff:
2025-07-02 04:52:31.708 # no non-identical "pretty close" pair
2025-07-02 04:52:31.708 if eqi is None:
2025-07-02 04:52:31.708 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.708 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.708 return
2025-07-02 04:52:31.709 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.709 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.709 else:
2025-07-02 04:52:31.709 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.709 eqi = None
2025-07-02 04:52:31.709
2025-07-02 04:52:31.709 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.709 # identical
2025-07-02 04:52:31.709
2025-07-02 04:52:31.709 # pump out diffs from before the synch point
2025-07-02 04:52:31.709 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.709
2025-07-02 04:52:31.709 # do intraline marking on the synch pair
2025-07-02 04:52:31.709 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.709 if eqi is None:
2025-07-02 04:52:31.709 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.709 atags = btags = ""
2025-07-02 04:52:31.709 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.709 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.709 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.710 if tag == 'replace':
2025-07-02 04:52:31.710 atags += '^' * la
2025-07-02 04:52:31.710 btags += '^' * lb
2025-07-02 04:52:31.710 elif tag == 'delete':
2025-07-02 04:52:31.710 atags += '-' * la
2025-07-02 04:52:31.710 elif tag == 'insert':
2025-07-02 04:52:31.710 btags += '+' * lb
2025-07-02 04:52:31.710 elif tag == 'equal':
2025-07-02 04:52:31.710 atags += ' ' * la
2025-07-02 04:52:31.710 btags += ' ' * lb
2025-07-02 04:52:31.710 else:
2025-07-02 04:52:31.710 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.710 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.710 else:
2025-07-02 04:52:31.710 # the synch pair is identical
2025-07-02 04:52:31.710 yield ' ' + aelt
2025-07-02 04:52:31.710
2025-07-02 04:52:31.710 # pump out diffs from after the synch point
2025-07-02 04:52:31.710 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.710
2025-07-02 04:52:31.711 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.711 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.711
2025-07-02 04:52:31.711 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.711 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.711 alo = 94, ahi = 1101
2025-07-02 04:52:31.711 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.711 blo = 94, bhi = 1101
2025-07-02 04:52:31.711
2025-07-02 04:52:31.711 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.711 g = []
2025-07-02 04:52:31.711 if alo < ahi:
2025-07-02 04:52:31.711 if blo < bhi:
2025-07-02 04:52:31.711 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.711 else:
2025-07-02 04:52:31.711 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.711 elif blo < bhi:
2025-07-02 04:52:31.711 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.711
2025-07-02 04:52:31.711 > yield from g
2025-07-02 04:52:31.711
2025-07-02 04:52:31.712 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.712 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.712
2025-07-02 04:52:31.712 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.712 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.712 alo = 94, ahi = 1101
2025-07-02 04:52:31.712 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.712 blo = 94, bhi = 1101
2025-07-02 04:52:31.712
2025-07-02 04:52:31.712 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.712 r"""
2025-07-02 04:52:31.712 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.712 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.712 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.712 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.712
2025-07-02 04:52:31.712 Example:
2025-07-02 04:52:31.712
2025-07-02 04:52:31.712 >>> d = Differ()
2025-07-02 04:52:31.712 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.713 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.713 >>> print(''.join(results), end="")
2025-07-02 04:52:31.713 - abcDefghiJkl
2025-07-02 04:52:31.713 + abcdefGhijkl
2025-07-02 04:52:31.713 """
2025-07-02 04:52:31.713
2025-07-02 04:52:31.713 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.713 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.713 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.713 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.713 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.713
2025-07-02 04:52:31.713 # search for the pair that matches best without being identical
2025-07-02 04:52:31.713 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.713 # on junk -- unless we have to)
2025-07-02 04:52:31.713 for j in range(blo, bhi):
2025-07-02 04:52:31.713 bj = b[j]
2025-07-02 04:52:31.713 cruncher.set_seq2(bj)
2025-07-02 04:52:31.713 for i in range(alo, ahi):
2025-07-02 04:52:31.714 ai = a[i]
2025-07-02 04:52:31.714 if ai == bj:
2025-07-02 04:52:31.714 if eqi is None:
2025-07-02 04:52:31.714 eqi, eqj = i, j
2025-07-02 04:52:31.714 continue
2025-07-02 04:52:31.714 cruncher.set_seq1(ai)
2025-07-02 04:52:31.714 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.714 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.714 # compares by a factor of 3.
2025-07-02 04:52:31.714 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.714 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.714 # of the computation is cached by cruncher
2025-07-02 04:52:31.714 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.714 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.714 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.714 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.714 if best_ratio < cutoff:
2025-07-02 04:52:31.714 # no non-identical "pretty close" pair
2025-07-02 04:52:31.714 if eqi is None:
2025-07-02 04:52:31.714 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.715 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.715 return
2025-07-02 04:52:31.715 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.715 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.715 else:
2025-07-02 04:52:31.715 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.715 eqi = None
2025-07-02 04:52:31.715
2025-07-02 04:52:31.715 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.715 # identical
2025-07-02 04:52:31.715
2025-07-02 04:52:31.715 # pump out diffs from before the synch point
2025-07-02 04:52:31.715 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.715
2025-07-02 04:52:31.715 # do intraline marking on the synch pair
2025-07-02 04:52:31.715 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.715 if eqi is None:
2025-07-02 04:52:31.715 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.715 atags = btags = ""
2025-07-02 04:52:31.715 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.715 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.716 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.716 if tag == 'replace':
2025-07-02 04:52:31.716 atags += '^' * la
2025-07-02 04:52:31.716 btags += '^' * lb
2025-07-02 04:52:31.716 elif tag == 'delete':
2025-07-02 04:52:31.716 atags += '-' * la
2025-07-02 04:52:31.716 elif tag == 'insert':
2025-07-02 04:52:31.716 btags += '+' * lb
2025-07-02 04:52:31.716 elif tag == 'equal':
2025-07-02 04:52:31.716 atags += ' ' * la
2025-07-02 04:52:31.716 btags += ' ' * lb
2025-07-02 04:52:31.716 else:
2025-07-02 04:52:31.716 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.716 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.716 else:
2025-07-02 04:52:31.716 # the synch pair is identical
2025-07-02 04:52:31.716 yield ' ' + aelt
2025-07-02 04:52:31.716
2025-07-02 04:52:31.716 # pump out diffs from after the synch point
2025-07-02 04:52:31.716 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.717
2025-07-02 04:52:31.717 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.717 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.717
2025-07-02 04:52:31.717 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.717 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.717 alo = 95, ahi = 1101
2025-07-02 04:52:31.717 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.717 blo = 95, bhi = 1101
2025-07-02 04:52:31.717
2025-07-02 04:52:31.717 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.717 g = []
2025-07-02 04:52:31.717 if alo < ahi:
2025-07-02 04:52:31.717 if blo < bhi:
2025-07-02 04:52:31.717 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.717 else:
2025-07-02 04:52:31.717 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.717 elif blo < bhi:
2025-07-02 04:52:31.717 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.717
2025-07-02 04:52:31.718 > yield from g
2025-07-02 04:52:31.718
2025-07-02 04:52:31.718 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.718 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.718
2025-07-02 04:52:31.718 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.718 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.718 alo = 95, ahi = 1101
2025-07-02 04:52:31.718 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.718 blo = 95, bhi = 1101
2025-07-02 04:52:31.718
2025-07-02 04:52:31.718 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.718 r"""
2025-07-02 04:52:31.718 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.718 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.718 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.718 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.718
2025-07-02 04:52:31.718 Example:
2025-07-02 04:52:31.718
2025-07-02 04:52:31.719 >>> d = Differ()
2025-07-02 04:52:31.719 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.719 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.719 >>> print(''.join(results), end="")
2025-07-02 04:52:31.719 - abcDefghiJkl
2025-07-02 04:52:31.719 + abcdefGhijkl
2025-07-02 04:52:31.719 """
2025-07-02 04:52:31.719
2025-07-02 04:52:31.719 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.719 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.719 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.719 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.719 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.719
2025-07-02 04:52:31.719 # search for the pair that matches best without being identical
2025-07-02 04:52:31.719 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.719 # on junk -- unless we have to)
2025-07-02 04:52:31.719 for j in range(blo, bhi):
2025-07-02 04:52:31.719 bj = b[j]
2025-07-02 04:52:31.720 cruncher.set_seq2(bj)
2025-07-02 04:52:31.720 for i in range(alo, ahi):
2025-07-02 04:52:31.720 ai = a[i]
2025-07-02 04:52:31.720 if ai == bj:
2025-07-02 04:52:31.720 if eqi is None:
2025-07-02 04:52:31.720 eqi, eqj = i, j
2025-07-02 04:52:31.720 continue
2025-07-02 04:52:31.720 cruncher.set_seq1(ai)
2025-07-02 04:52:31.720 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.720 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.720 # compares by a factor of 3.
2025-07-02 04:52:31.720 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.720 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.720 # of the computation is cached by cruncher
2025-07-02 04:52:31.720 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.720 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.720 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.720 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.720 if best_ratio < cutoff:
2025-07-02 04:52:31.720 # no non-identical "pretty close" pair
2025-07-02 04:52:31.720 if eqi is None:
2025-07-02 04:52:31.721 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.721 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.721 return
2025-07-02 04:52:31.721 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.721 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.721 else:
2025-07-02 04:52:31.721 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.721 eqi = None
2025-07-02 04:52:31.721
2025-07-02 04:52:31.721 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.721 # identical
2025-07-02 04:52:31.721
2025-07-02 04:52:31.721 # pump out diffs from before the synch point
2025-07-02 04:52:31.721 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.721
2025-07-02 04:52:31.721 # do intraline marking on the synch pair
2025-07-02 04:52:31.721 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.721 if eqi is None:
2025-07-02 04:52:31.721 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.721 atags = btags = ""
2025-07-02 04:52:31.722 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.722 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.722 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.722 if tag == 'replace':
2025-07-02 04:52:31.722 atags += '^' * la
2025-07-02 04:52:31.722 btags += '^' * lb
2025-07-02 04:52:31.722 elif tag == 'delete':
2025-07-02 04:52:31.722 atags += '-' * la
2025-07-02 04:52:31.722 elif tag == 'insert':
2025-07-02 04:52:31.722 btags += '+' * lb
2025-07-02 04:52:31.722 elif tag == 'equal':
2025-07-02 04:52:31.722 atags += ' ' * la
2025-07-02 04:52:31.722 btags += ' ' * lb
2025-07-02 04:52:31.722 else:
2025-07-02 04:52:31.722 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.722 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.722 else:
2025-07-02 04:52:31.722 # the synch pair is identical
2025-07-02 04:52:31.722 yield ' ' + aelt
2025-07-02 04:52:31.722
2025-07-02 04:52:31.722 # pump out diffs from after the synch point
2025-07-02 04:52:31.723 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.723
2025-07-02 04:52:31.723 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.723 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.723
2025-07-02 04:52:31.723 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.723 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.723 alo = 96, ahi = 1101
2025-07-02 04:52:31.723 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.723 blo = 96, bhi = 1101
2025-07-02 04:52:31.723
2025-07-02 04:52:31.723 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.723 g = []
2025-07-02 04:52:31.723 if alo < ahi:
2025-07-02 04:52:31.723 if blo < bhi:
2025-07-02 04:52:31.723 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.723 else:
2025-07-02 04:52:31.723 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.724 elif blo < bhi:
2025-07-02 04:52:31.724 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.724
2025-07-02 04:52:31.724 > yield from g
2025-07-02 04:52:31.724
2025-07-02 04:52:31.724 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.724 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.724
2025-07-02 04:52:31.724 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.724 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.724 alo = 96, ahi = 1101
2025-07-02 04:52:31.724 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.724 blo = 96, bhi = 1101
2025-07-02 04:52:31.724
2025-07-02 04:52:31.724 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.724 r"""
2025-07-02 04:52:31.724 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.724 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.724 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.724 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.725
2025-07-02 04:52:31.725 Example:
2025-07-02 04:52:31.725
2025-07-02 04:52:31.725 >>> d = Differ()
2025-07-02 04:52:31.725 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.725 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.725 >>> print(''.join(results), end="")
2025-07-02 04:52:31.725 - abcDefghiJkl
2025-07-02 04:52:31.725 + abcdefGhijkl
2025-07-02 04:52:31.725 """
2025-07-02 04:52:31.725
2025-07-02 04:52:31.725 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.725 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.725 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.725 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.725 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.725
2025-07-02 04:52:31.725 # search for the pair that matches best without being identical
2025-07-02 04:52:31.725 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.726 # on junk -- unless we have to)
2025-07-02 04:52:31.726 for j in range(blo, bhi):
2025-07-02 04:52:31.726 bj = b[j]
2025-07-02 04:52:31.726 cruncher.set_seq2(bj)
2025-07-02 04:52:31.726 for i in range(alo, ahi):
2025-07-02 04:52:31.726 ai = a[i]
2025-07-02 04:52:31.726 if ai == bj:
2025-07-02 04:52:31.726 if eqi is None:
2025-07-02 04:52:31.726 eqi, eqj = i, j
2025-07-02 04:52:31.726 continue
2025-07-02 04:52:31.726 cruncher.set_seq1(ai)
2025-07-02 04:52:31.726 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.726 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.726 # compares by a factor of 3.
2025-07-02 04:52:31.726 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.726 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.726 # of the computation is cached by cruncher
2025-07-02 04:52:31.726 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.726 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.727 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.727 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.727 if best_ratio < cutoff:
2025-07-02 04:52:31.727 # no non-identical "pretty close" pair
2025-07-02 04:52:31.727 if eqi is None:
2025-07-02 04:52:31.727 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.727 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.727 return
2025-07-02 04:52:31.727 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.727 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.727 else:
2025-07-02 04:52:31.727 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.727 eqi = None
2025-07-02 04:52:31.727
2025-07-02 04:52:31.727 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.727 # identical
2025-07-02 04:52:31.727
2025-07-02 04:52:31.727 # pump out diffs from before the synch point
2025-07-02 04:52:31.727 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.727
2025-07-02 04:52:31.727 # do intraline marking on the synch pair
2025-07-02 04:52:31.728 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.728 if eqi is None:
2025-07-02 04:52:31.728 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.728 atags = btags = ""
2025-07-02 04:52:31.728 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.728 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.728 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.728 if tag == 'replace':
2025-07-02 04:52:31.728 atags += '^' * la
2025-07-02 04:52:31.728 btags += '^' * lb
2025-07-02 04:52:31.728 elif tag == 'delete':
2025-07-02 04:52:31.728 atags += '-' * la
2025-07-02 04:52:31.728 elif tag == 'insert':
2025-07-02 04:52:31.728 btags += '+' * lb
2025-07-02 04:52:31.728 elif tag == 'equal':
2025-07-02 04:52:31.728 atags += ' ' * la
2025-07-02 04:52:31.728 btags += ' ' * lb
2025-07-02 04:52:31.728 else:
2025-07-02 04:52:31.728 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.728 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.728 else:
2025-07-02 04:52:31.729 # the synch pair is identical
2025-07-02 04:52:31.729 yield ' ' + aelt
2025-07-02 04:52:31.729
2025-07-02 04:52:31.729 # pump out diffs from after the synch point
2025-07-02 04:52:31.729 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.729
2025-07-02 04:52:31.729 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.729 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.729
2025-07-02 04:52:31.729 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.729 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.729 alo = 97, ahi = 1101
2025-07-02 04:52:31.729 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.729 blo = 97, bhi = 1101
2025-07-02 04:52:31.729
2025-07-02 04:52:31.729 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.729 g = []
2025-07-02 04:52:31.729 if alo < ahi:
2025-07-02 04:52:31.729 if blo < bhi:
2025-07-02 04:52:31.729 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.730 else:
2025-07-02 04:52:31.730 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.730 elif blo < bhi:
2025-07-02 04:52:31.730 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.730
2025-07-02 04:52:31.730 > yield from g
2025-07-02 04:52:31.730
2025-07-02 04:52:31.730 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.730 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.730
2025-07-02 04:52:31.730 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.730 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.730 alo = 97, ahi = 1101
2025-07-02 04:52:31.730 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.730 blo = 97, bhi = 1101
2025-07-02 04:52:31.730
2025-07-02 04:52:31.730 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.730 r"""
2025-07-02 04:52:31.730 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.730 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.731 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.731 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.731
2025-07-02 04:52:31.731 Example:
2025-07-02 04:52:31.731
2025-07-02 04:52:31.731 >>> d = Differ()
2025-07-02 04:52:31.731 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.731 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.731 >>> print(''.join(results), end="")
2025-07-02 04:52:31.731 - abcDefghiJkl
2025-07-02 04:52:31.731 + abcdefGhijkl
2025-07-02 04:52:31.731 """
2025-07-02 04:52:31.731
2025-07-02 04:52:31.731 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.731 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.731 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.731 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.731 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.731
2025-07-02 04:52:31.732 # search for the pair that matches best without being identical
2025-07-02 04:52:31.732 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.732 # on junk -- unless we have to)
2025-07-02 04:52:31.732 for j in range(blo, bhi):
2025-07-02 04:52:31.732 bj = b[j]
2025-07-02 04:52:31.732 cruncher.set_seq2(bj)
2025-07-02 04:52:31.732 for i in range(alo, ahi):
2025-07-02 04:52:31.732 ai = a[i]
2025-07-02 04:52:31.732 if ai == bj:
2025-07-02 04:52:31.732 if eqi is None:
2025-07-02 04:52:31.732 eqi, eqj = i, j
2025-07-02 04:52:31.732 continue
2025-07-02 04:52:31.732 cruncher.set_seq1(ai)
2025-07-02 04:52:31.732 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.732 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.732 # compares by a factor of 3.
2025-07-02 04:52:31.732 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.732 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.732 # of the computation is cached by cruncher
2025-07-02 04:52:31.732 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.732 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.733 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.733 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.733 if best_ratio < cutoff:
2025-07-02 04:52:31.733 # no non-identical "pretty close" pair
2025-07-02 04:52:31.733 if eqi is None:
2025-07-02 04:52:31.733 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.733 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.733 return
2025-07-02 04:52:31.733 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.733 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.733 else:
2025-07-02 04:52:31.733 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.733 eqi = None
2025-07-02 04:52:31.733
2025-07-02 04:52:31.733 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.733 # identical
2025-07-02 04:52:31.733
2025-07-02 04:52:31.733 # pump out diffs from before the synch point
2025-07-02 04:52:31.733 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.733
2025-07-02 04:52:31.734 # do intraline marking on the synch pair
2025-07-02 04:52:31.734 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.734 if eqi is None:
2025-07-02 04:52:31.734 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.734 atags = btags = ""
2025-07-02 04:52:31.734 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.734 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.734 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.734 if tag == 'replace':
2025-07-02 04:52:31.734 atags += '^' * la
2025-07-02 04:52:31.734 btags += '^' * lb
2025-07-02 04:52:31.734 elif tag == 'delete':
2025-07-02 04:52:31.734 atags += '-' * la
2025-07-02 04:52:31.734 elif tag == 'insert':
2025-07-02 04:52:31.734 btags += '+' * lb
2025-07-02 04:52:31.734 elif tag == 'equal':
2025-07-02 04:52:31.734 atags += ' ' * la
2025-07-02 04:52:31.734 btags += ' ' * lb
2025-07-02 04:52:31.734 else:
2025-07-02 04:52:31.734 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.734 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.735 else:
2025-07-02 04:52:31.735 # the synch pair is identical
2025-07-02 04:52:31.735 yield ' ' + aelt
2025-07-02 04:52:31.735
2025-07-02 04:52:31.735 # pump out diffs from after the synch point
2025-07-02 04:52:31.735 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.735
2025-07-02 04:52:31.735 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.735 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.735
2025-07-02 04:52:31.735 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.735 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.735 alo = 98, ahi = 1101
2025-07-02 04:52:31.735 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.735 blo = 98, bhi = 1101
2025-07-02 04:52:31.735
2025-07-02 04:52:31.735 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.735 g = []
2025-07-02 04:52:31.735 if alo < ahi:
2025-07-02 04:52:31.735 if blo < bhi:
2025-07-02 04:52:31.736 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.736 else:
2025-07-02 04:52:31.736 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.736 elif blo < bhi:
2025-07-02 04:52:31.736 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.736
2025-07-02 04:52:31.736 > yield from g
2025-07-02 04:52:31.736
2025-07-02 04:52:31.736 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.736 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.736
2025-07-02 04:52:31.736 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.736 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.736 alo = 98, ahi = 1101
2025-07-02 04:52:31.736 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.736 blo = 98, bhi = 1101
2025-07-02 04:52:31.736
2025-07-02 04:52:31.736 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.736 r"""
2025-07-02 04:52:31.736 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.737 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.737 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.737 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.737
2025-07-02 04:52:31.737 Example:
2025-07-02 04:52:31.737
2025-07-02 04:52:31.737 >>> d = Differ()
2025-07-02 04:52:31.737 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.737 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.737 >>> print(''.join(results), end="")
2025-07-02 04:52:31.737 - abcDefghiJkl
2025-07-02 04:52:31.737 + abcdefGhijkl
2025-07-02 04:52:31.737 """
2025-07-02 04:52:31.737
2025-07-02 04:52:31.737 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.737 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.737 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.737 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.737 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.738
2025-07-02 04:52:31.738 # search for the pair that matches best without being identical
2025-07-02 04:52:31.738 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.738 # on junk -- unless we have to)
2025-07-02 04:52:31.738 for j in range(blo, bhi):
2025-07-02 04:52:31.738 bj = b[j]
2025-07-02 04:52:31.738 cruncher.set_seq2(bj)
2025-07-02 04:52:31.738 for i in range(alo, ahi):
2025-07-02 04:52:31.738 ai = a[i]
2025-07-02 04:52:31.738 if ai == bj:
2025-07-02 04:52:31.738 if eqi is None:
2025-07-02 04:52:31.738 eqi, eqj = i, j
2025-07-02 04:52:31.738 continue
2025-07-02 04:52:31.738 cruncher.set_seq1(ai)
2025-07-02 04:52:31.738 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.738 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.738 # compares by a factor of 3.
2025-07-02 04:52:31.738 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.738 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.738 # of the computation is cached by cruncher
2025-07-02 04:52:31.738 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.739 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.739 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.739 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.739 if best_ratio < cutoff:
2025-07-02 04:52:31.739 # no non-identical "pretty close" pair
2025-07-02 04:52:31.739 if eqi is None:
2025-07-02 04:52:31.739 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.739 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.739 return
2025-07-02 04:52:31.739 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.739 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.739 else:
2025-07-02 04:52:31.739 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.739 eqi = None
2025-07-02 04:52:31.739
2025-07-02 04:52:31.739 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.739 # identical
2025-07-02 04:52:31.739
2025-07-02 04:52:31.739 # pump out diffs from before the synch point
2025-07-02 04:52:31.739 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.740
2025-07-02 04:52:31.740 # do intraline marking on the synch pair
2025-07-02 04:52:31.740 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.740 if eqi is None:
2025-07-02 04:52:31.740 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.740 atags = btags = ""
2025-07-02 04:52:31.740 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.740 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.740 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.740 if tag == 'replace':
2025-07-02 04:52:31.740 atags += '^' * la
2025-07-02 04:52:31.740 btags += '^' * lb
2025-07-02 04:52:31.740 elif tag == 'delete':
2025-07-02 04:52:31.740 atags += '-' * la
2025-07-02 04:52:31.740 elif tag == 'insert':
2025-07-02 04:52:31.740 btags += '+' * lb
2025-07-02 04:52:31.740 elif tag == 'equal':
2025-07-02 04:52:31.740 atags += ' ' * la
2025-07-02 04:52:31.740 btags += ' ' * lb
2025-07-02 04:52:31.740 else:
2025-07-02 04:52:31.741 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.741 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.741 else:
2025-07-02 04:52:31.741 # the synch pair is identical
2025-07-02 04:52:31.741 yield ' ' + aelt
2025-07-02 04:52:31.741
2025-07-02 04:52:31.741 # pump out diffs from after the synch point
2025-07-02 04:52:31.741 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.741
2025-07-02 04:52:31.741 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.741 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.741
2025-07-02 04:52:31.741 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.741 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.741 alo = 99, ahi = 1101
2025-07-02 04:52:31.741 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.741 blo = 99, bhi = 1101
2025-07-02 04:52:31.741
2025-07-02 04:52:31.741 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.741 g = []
2025-07-02 04:52:31.741 if alo < ahi:
2025-07-02 04:52:31.742 if blo < bhi:
2025-07-02 04:52:31.742 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.742 else:
2025-07-02 04:52:31.742 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.742 elif blo < bhi:
2025-07-02 04:52:31.742 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.742
2025-07-02 04:52:31.742 > yield from g
2025-07-02 04:52:31.742
2025-07-02 04:52:31.742 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.742 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.742
2025-07-02 04:52:31.742 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.742 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.742 alo = 99, ahi = 1101
2025-07-02 04:52:31.742 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.742 blo = 99, bhi = 1101
2025-07-02 04:52:31.742
2025-07-02 04:52:31.742 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.742 r"""
2025-07-02 04:52:31.743 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.743 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.743 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.743 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.743
2025-07-02 04:52:31.743 Example:
2025-07-02 04:52:31.743
2025-07-02 04:52:31.743 >>> d = Differ()
2025-07-02 04:52:31.743 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.743 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.743 >>> print(''.join(results), end="")
2025-07-02 04:52:31.743 - abcDefghiJkl
2025-07-02 04:52:31.743 + abcdefGhijkl
2025-07-02 04:52:31.743 """
2025-07-02 04:52:31.743
2025-07-02 04:52:31.743 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.743 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.744 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.744 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.744 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.744
2025-07-02 04:52:31.744 # search for the pair that matches best without being identical
2025-07-02 04:52:31.744 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.744 # on junk -- unless we have to)
2025-07-02 04:52:31.744 for j in range(blo, bhi):
2025-07-02 04:52:31.744 bj = b[j]
2025-07-02 04:52:31.744 cruncher.set_seq2(bj)
2025-07-02 04:52:31.744 for i in range(alo, ahi):
2025-07-02 04:52:31.744 ai = a[i]
2025-07-02 04:52:31.744 if ai == bj:
2025-07-02 04:52:31.744 if eqi is None:
2025-07-02 04:52:31.744 eqi, eqj = i, j
2025-07-02 04:52:31.744 continue
2025-07-02 04:52:31.744 cruncher.set_seq1(ai)
2025-07-02 04:52:31.744 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.744 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.744 # compares by a factor of 3.
2025-07-02 04:52:31.744 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.745 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.745 # of the computation is cached by cruncher
2025-07-02 04:52:31.745 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.745 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.745 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.745 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.745 if best_ratio < cutoff:
2025-07-02 04:52:31.745 # no non-identical "pretty close" pair
2025-07-02 04:52:31.745 if eqi is None:
2025-07-02 04:52:31.745 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.745 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.745 return
2025-07-02 04:52:31.745 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.745 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.745 else:
2025-07-02 04:52:31.745 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.745 eqi = None
2025-07-02 04:52:31.745
2025-07-02 04:52:31.745 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.745 # identical
2025-07-02 04:52:31.746
2025-07-02 04:52:31.746 # pump out diffs from before the synch point
2025-07-02 04:52:31.746 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.746
2025-07-02 04:52:31.746 # do intraline marking on the synch pair
2025-07-02 04:52:31.746 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.746 if eqi is None:
2025-07-02 04:52:31.746 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.746 atags = btags = ""
2025-07-02 04:52:31.746 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.746 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.746 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.746 if tag == 'replace':
2025-07-02 04:52:31.746 atags += '^' * la
2025-07-02 04:52:31.746 btags += '^' * lb
2025-07-02 04:52:31.746 elif tag == 'delete':
2025-07-02 04:52:31.746 atags += '-' * la
2025-07-02 04:52:31.746 elif tag == 'insert':
2025-07-02 04:52:31.746 btags += '+' * lb
2025-07-02 04:52:31.746 elif tag == 'equal':
2025-07-02 04:52:31.746 atags += ' ' * la
2025-07-02 04:52:31.747 btags += ' ' * lb
2025-07-02 04:52:31.747 else:
2025-07-02 04:52:31.747 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.747 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.747 else:
2025-07-02 04:52:31.747 # the synch pair is identical
2025-07-02 04:52:31.747 yield ' ' + aelt
2025-07-02 04:52:31.747
2025-07-02 04:52:31.747 # pump out diffs from after the synch point
2025-07-02 04:52:31.747 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.747
2025-07-02 04:52:31.747 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.747 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.747
2025-07-02 04:52:31.747 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.747 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.747 alo = 100, ahi = 1101
2025-07-02 04:52:31.747 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.747 blo = 100, bhi = 1101
2025-07-02 04:52:31.747
2025-07-02 04:52:31.748 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.748 g = []
2025-07-02 04:52:31.748 if alo < ahi:
2025-07-02 04:52:31.748 if blo < bhi:
2025-07-02 04:52:31.748 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.748 else:
2025-07-02 04:52:31.748 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.748 elif blo < bhi:
2025-07-02 04:52:31.748 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.748
2025-07-02 04:52:31.748 > yield from g
2025-07-02 04:52:31.748
2025-07-02 04:52:31.748 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.748 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.748
2025-07-02 04:52:31.748 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.748 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.748 alo = 100, ahi = 1101
2025-07-02 04:52:31.748 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.748 blo = 100, bhi = 1101
2025-07-02 04:52:31.748
2025-07-02 04:52:31.749 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.749 r"""
2025-07-02 04:52:31.749 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.749 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.749 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.749 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.749
2025-07-02 04:52:31.749 Example:
2025-07-02 04:52:31.749
2025-07-02 04:52:31.749 >>> d = Differ()
2025-07-02 04:52:31.749 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.749 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.749 >>> print(''.join(results), end="")
2025-07-02 04:52:31.749 - abcDefghiJkl
2025-07-02 04:52:31.749 + abcdefGhijkl
2025-07-02 04:52:31.749 """
2025-07-02 04:52:31.749
2025-07-02 04:52:31.749 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.750 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.750 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.750 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.750 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.750
2025-07-02 04:52:31.750 # search for the pair that matches best without being identical
2025-07-02 04:52:31.750 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.750 # on junk -- unless we have to)
2025-07-02 04:52:31.750 for j in range(blo, bhi):
2025-07-02 04:52:31.750 bj = b[j]
2025-07-02 04:52:31.750 cruncher.set_seq2(bj)
2025-07-02 04:52:31.750 for i in range(alo, ahi):
2025-07-02 04:52:31.750 ai = a[i]
2025-07-02 04:52:31.750 if ai == bj:
2025-07-02 04:52:31.750 if eqi is None:
2025-07-02 04:52:31.750 eqi, eqj = i, j
2025-07-02 04:52:31.750 continue
2025-07-02 04:52:31.750 cruncher.set_seq1(ai)
2025-07-02 04:52:31.750 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.750 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.750 # compares by a factor of 3.
2025-07-02 04:52:31.751 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.751 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.751 # of the computation is cached by cruncher
2025-07-02 04:52:31.751 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.751 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.751 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.751 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.751 if best_ratio < cutoff:
2025-07-02 04:52:31.751 # no non-identical "pretty close" pair
2025-07-02 04:52:31.751 if eqi is None:
2025-07-02 04:52:31.751 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.751 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.751 return
2025-07-02 04:52:31.751 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.751 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.751 else:
2025-07-02 04:52:31.751 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.751 eqi = None
2025-07-02 04:52:31.751
2025-07-02 04:52:31.751 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.752 # identical
2025-07-02 04:52:31.752
2025-07-02 04:52:31.752 # pump out diffs from before the synch point
2025-07-02 04:52:31.752 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.752
2025-07-02 04:52:31.752 # do intraline marking on the synch pair
2025-07-02 04:52:31.752 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.752 if eqi is None:
2025-07-02 04:52:31.752 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.752 atags = btags = ""
2025-07-02 04:52:31.752 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.752 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.752 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.752 if tag == 'replace':
2025-07-02 04:52:31.752 atags += '^' * la
2025-07-02 04:52:31.752 btags += '^' * lb
2025-07-02 04:52:31.752 elif tag == 'delete':
2025-07-02 04:52:31.752 atags += '-' * la
2025-07-02 04:52:31.752 elif tag == 'insert':
2025-07-02 04:52:31.752 btags += '+' * lb
2025-07-02 04:52:31.752 elif tag == 'equal':
2025-07-02 04:52:31.753 atags += ' ' * la
2025-07-02 04:52:31.753 btags += ' ' * lb
2025-07-02 04:52:31.753 else:
2025-07-02 04:52:31.753 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.753 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.753 else:
2025-07-02 04:52:31.753 # the synch pair is identical
2025-07-02 04:52:31.753 yield ' ' + aelt
2025-07-02 04:52:31.753
2025-07-02 04:52:31.753 # pump out diffs from after the synch point
2025-07-02 04:52:31.753 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.753
2025-07-02 04:52:31.753 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.753 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.753
2025-07-02 04:52:31.753 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.753 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.753 alo = 101, ahi = 1101
2025-07-02 04:52:31.753 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.753 blo = 101, bhi = 1101
2025-07-02 04:52:31.754
2025-07-02 04:52:31.754 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.754 g = []
2025-07-02 04:52:31.754 if alo < ahi:
2025-07-02 04:52:31.754 if blo < bhi:
2025-07-02 04:52:31.754 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.754 else:
2025-07-02 04:52:31.754 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.754 elif blo < bhi:
2025-07-02 04:52:31.754 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.754
2025-07-02 04:52:31.754 > yield from g
2025-07-02 04:52:31.754
2025-07-02 04:52:31.754 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.754 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.754
2025-07-02 04:52:31.754 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.754 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.755 alo = 101, ahi = 1101
2025-07-02 04:52:31.755 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.755 blo = 101, bhi = 1101
2025-07-02 04:52:31.755
2025-07-02 04:52:31.755 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.755 r"""
2025-07-02 04:52:31.755 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.755 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.755 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.755 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.755
2025-07-02 04:52:31.755 Example:
2025-07-02 04:52:31.755
2025-07-02 04:52:31.755 >>> d = Differ()
2025-07-02 04:52:31.755 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.755 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.755 >>> print(''.join(results), end="")
2025-07-02 04:52:31.755 - abcDefghiJkl
2025-07-02 04:52:31.755 + abcdefGhijkl
2025-07-02 04:52:31.756 """
2025-07-02 04:52:31.756
2025-07-02 04:52:31.756 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.756 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.756 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.756 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.756 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.756
2025-07-02 04:52:31.756 # search for the pair that matches best without being identical
2025-07-02 04:52:31.756 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.756 # on junk -- unless we have to)
2025-07-02 04:52:31.756 for j in range(blo, bhi):
2025-07-02 04:52:31.756 bj = b[j]
2025-07-02 04:52:31.756 cruncher.set_seq2(bj)
2025-07-02 04:52:31.756 for i in range(alo, ahi):
2025-07-02 04:52:31.756 ai = a[i]
2025-07-02 04:52:31.756 if ai == bj:
2025-07-02 04:52:31.756 if eqi is None:
2025-07-02 04:52:31.756 eqi, eqj = i, j
2025-07-02 04:52:31.756 continue
2025-07-02 04:52:31.757 cruncher.set_seq1(ai)
2025-07-02 04:52:31.757 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.757 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.757 # compares by a factor of 3.
2025-07-02 04:52:31.757 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.757 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.757 # of the computation is cached by cruncher
2025-07-02 04:52:31.757 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.757 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.757 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.757 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.757 if best_ratio < cutoff:
2025-07-02 04:52:31.757 # no non-identical "pretty close" pair
2025-07-02 04:52:31.757 if eqi is None:
2025-07-02 04:52:31.757 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.757 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.757 return
2025-07-02 04:52:31.757 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.757 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.757 else:
2025-07-02 04:52:31.758 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.758 eqi = None
2025-07-02 04:52:31.758
2025-07-02 04:52:31.758 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.758 # identical
2025-07-02 04:52:31.758
2025-07-02 04:52:31.758 # pump out diffs from before the synch point
2025-07-02 04:52:31.758 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.758
2025-07-02 04:52:31.758 # do intraline marking on the synch pair
2025-07-02 04:52:31.758 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.758 if eqi is None:
2025-07-02 04:52:31.758 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.758 atags = btags = ""
2025-07-02 04:52:31.758 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.758 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.758 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.758 if tag == 'replace':
2025-07-02 04:52:31.758 atags += '^' * la
2025-07-02 04:52:31.758 btags += '^' * lb
2025-07-02 04:52:31.758 elif tag == 'delete':
2025-07-02 04:52:31.759 atags += '-' * la
2025-07-02 04:52:31.759 elif tag == 'insert':
2025-07-02 04:52:31.759 btags += '+' * lb
2025-07-02 04:52:31.759 elif tag == 'equal':
2025-07-02 04:52:31.759 atags += ' ' * la
2025-07-02 04:52:31.759 btags += ' ' * lb
2025-07-02 04:52:31.759 else:
2025-07-02 04:52:31.759 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.759 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.759 else:
2025-07-02 04:52:31.759 # the synch pair is identical
2025-07-02 04:52:31.759 yield ' ' + aelt
2025-07-02 04:52:31.759
2025-07-02 04:52:31.759 # pump out diffs from after the synch point
2025-07-02 04:52:31.759 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.759
2025-07-02 04:52:31.759 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.759 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.759
2025-07-02 04:52:31.759 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.759 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.760 alo = 102, ahi = 1101
2025-07-02 04:52:31.760 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.760 blo = 102, bhi = 1101
2025-07-02 04:52:31.760
2025-07-02 04:52:31.760 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.760 g = []
2025-07-02 04:52:31.760 if alo < ahi:
2025-07-02 04:52:31.760 if blo < bhi:
2025-07-02 04:52:31.760 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.760 else:
2025-07-02 04:52:31.760 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.760 elif blo < bhi:
2025-07-02 04:52:31.760 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.760
2025-07-02 04:52:31.760 > yield from g
2025-07-02 04:52:31.760
2025-07-02 04:52:31.760 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.760 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.761
2025-07-02 04:52:31.761 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.761 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.761 alo = 102, ahi = 1101
2025-07-02 04:52:31.761 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.761 blo = 102, bhi = 1101
2025-07-02 04:52:31.761
2025-07-02 04:52:31.761 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.761 r"""
2025-07-02 04:52:31.761 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.761 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.761 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.761 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.761
2025-07-02 04:52:31.761 Example:
2025-07-02 04:52:31.761
2025-07-02 04:52:31.761 >>> d = Differ()
2025-07-02 04:52:31.761 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.761 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.761 >>> print(''.join(results), end="")
2025-07-02 04:52:31.762 - abcDefghiJkl
2025-07-02 04:52:31.762 + abcdefGhijkl
2025-07-02 04:52:31.762 """
2025-07-02 04:52:31.762
2025-07-02 04:52:31.762 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.762 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.762 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.762 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.762 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.762
2025-07-02 04:52:31.762 # search for the pair that matches best without being identical
2025-07-02 04:52:31.762 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.762 # on junk -- unless we have to)
2025-07-02 04:52:31.762 for j in range(blo, bhi):
2025-07-02 04:52:31.762 bj = b[j]
2025-07-02 04:52:31.762 cruncher.set_seq2(bj)
2025-07-02 04:52:31.762 for i in range(alo, ahi):
2025-07-02 04:52:31.762 ai = a[i]
2025-07-02 04:52:31.762 if ai == bj:
2025-07-02 04:52:31.763 if eqi is None:
2025-07-02 04:52:31.763 eqi, eqj = i, j
2025-07-02 04:52:31.763 continue
2025-07-02 04:52:31.763 cruncher.set_seq1(ai)
2025-07-02 04:52:31.763 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.763 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.763 # compares by a factor of 3.
2025-07-02 04:52:31.763 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.763 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.763 # of the computation is cached by cruncher
2025-07-02 04:52:31.763 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.763 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.763 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.763 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.763 if best_ratio < cutoff:
2025-07-02 04:52:31.763 # no non-identical "pretty close" pair
2025-07-02 04:52:31.763 if eqi is None:
2025-07-02 04:52:31.763 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.763 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.763 return
2025-07-02 04:52:31.764 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.764 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.764 else:
2025-07-02 04:52:31.764 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.764 eqi = None
2025-07-02 04:52:31.764
2025-07-02 04:52:31.764 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.764 # identical
2025-07-02 04:52:31.764
2025-07-02 04:52:31.764 # pump out diffs from before the synch point
2025-07-02 04:52:31.764 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.764
2025-07-02 04:52:31.764 # do intraline marking on the synch pair
2025-07-02 04:52:31.764 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.765 if eqi is None:
2025-07-02 04:52:31.765 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.765 atags = btags = ""
2025-07-02 04:52:31.765 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.765 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.765 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.765 if tag == 'replace':
2025-07-02 04:52:31.765 atags += '^' * la
2025-07-02 04:52:31.765 btags += '^' * lb
2025-07-02 04:52:31.765 elif tag == 'delete':
2025-07-02 04:52:31.765 atags += '-' * la
2025-07-02 04:52:31.765 elif tag == 'insert':
2025-07-02 04:52:31.765 btags += '+' * lb
2025-07-02 04:52:31.765 elif tag == 'equal':
2025-07-02 04:52:31.765 atags += ' ' * la
2025-07-02 04:52:31.765 btags += ' ' * lb
2025-07-02 04:52:31.765 else:
2025-07-02 04:52:31.765 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.765 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.765 else:
2025-07-02 04:52:31.766 # the synch pair is identical
2025-07-02 04:52:31.766 yield ' ' + aelt
2025-07-02 04:52:31.766
2025-07-02 04:52:31.766 # pump out diffs from after the synch point
2025-07-02 04:52:31.766 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.766
2025-07-02 04:52:31.766 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.766 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.766
2025-07-02 04:52:31.766 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.766 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.766 alo = 103, ahi = 1101
2025-07-02 04:52:31.766 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.766 blo = 103, bhi = 1101
2025-07-02 04:52:31.766
2025-07-02 04:52:31.766 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.766 g = []
2025-07-02 04:52:31.766 if alo < ahi:
2025-07-02 04:52:31.766 if blo < bhi:
2025-07-02 04:52:31.766 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.766 else:
2025-07-02 04:52:31.767 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.767 elif blo < bhi:
2025-07-02 04:52:31.767 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.767
2025-07-02 04:52:31.767 > yield from g
2025-07-02 04:52:31.767
2025-07-02 04:52:31.767 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.767 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.767
2025-07-02 04:52:31.767 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.767 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.767 alo = 103, ahi = 1101
2025-07-02 04:52:31.767 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.767 blo = 103, bhi = 1101
2025-07-02 04:52:31.767
2025-07-02 04:52:31.767 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.767 r"""
2025-07-02 04:52:31.767 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.767 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.767 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.767 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.768
2025-07-02 04:52:31.768 Example:
2025-07-02 04:52:31.768
2025-07-02 04:52:31.768 >>> d = Differ()
2025-07-02 04:52:31.768 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.768 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.768 >>> print(''.join(results), end="")
2025-07-02 04:52:31.768 - abcDefghiJkl
2025-07-02 04:52:31.768 + abcdefGhijkl
2025-07-02 04:52:31.768 """
2025-07-02 04:52:31.768
2025-07-02 04:52:31.768 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.768 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.768 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.768 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.768 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.768
2025-07-02 04:52:31.768 # search for the pair that matches best without being identical
2025-07-02 04:52:31.768 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.769 # on junk -- unless we have to)
2025-07-02 04:52:31.769 for j in range(blo, bhi):
2025-07-02 04:52:31.769 bj = b[j]
2025-07-02 04:52:31.769 cruncher.set_seq2(bj)
2025-07-02 04:52:31.769 for i in range(alo, ahi):
2025-07-02 04:52:31.769 ai = a[i]
2025-07-02 04:52:31.769 if ai == bj:
2025-07-02 04:52:31.769 if eqi is None:
2025-07-02 04:52:31.769 eqi, eqj = i, j
2025-07-02 04:52:31.769 continue
2025-07-02 04:52:31.769 cruncher.set_seq1(ai)
2025-07-02 04:52:31.769 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.769 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.769 # compares by a factor of 3.
2025-07-02 04:52:31.769 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.769 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.769 # of the computation is cached by cruncher
2025-07-02 04:52:31.769 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.769 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.770 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.770 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.770 if best_ratio < cutoff:
2025-07-02 04:52:31.770 # no non-identical "pretty close" pair
2025-07-02 04:52:31.770 if eqi is None:
2025-07-02 04:52:31.770 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.770 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.770 return
2025-07-02 04:52:31.770 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.770 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.770 else:
2025-07-02 04:52:31.770 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.770 eqi = None
2025-07-02 04:52:31.770
2025-07-02 04:52:31.770 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.770 # identical
2025-07-02 04:52:31.770
2025-07-02 04:52:31.770 # pump out diffs from before the synch point
2025-07-02 04:52:31.770 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.770
2025-07-02 04:52:31.770 # do intraline marking on the synch pair
2025-07-02 04:52:31.771 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.771 if eqi is None:
2025-07-02 04:52:31.771 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.771 atags = btags = ""
2025-07-02 04:52:31.771 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.771 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.771 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.771 if tag == 'replace':
2025-07-02 04:52:31.771 atags += '^' * la
2025-07-02 04:52:31.771 btags += '^' * lb
2025-07-02 04:52:31.771 elif tag == 'delete':
2025-07-02 04:52:31.771 atags += '-' * la
2025-07-02 04:52:31.771 elif tag == 'insert':
2025-07-02 04:52:31.771 btags += '+' * lb
2025-07-02 04:52:31.771 elif tag == 'equal':
2025-07-02 04:52:31.771 atags += ' ' * la
2025-07-02 04:52:31.771 btags += ' ' * lb
2025-07-02 04:52:31.771 else:
2025-07-02 04:52:31.771 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.771 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.771 else:
2025-07-02 04:52:31.772 # the synch pair is identical
2025-07-02 04:52:31.772 yield ' ' + aelt
2025-07-02 04:52:31.772
2025-07-02 04:52:31.772 # pump out diffs from after the synch point
2025-07-02 04:52:31.772 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.772
2025-07-02 04:52:31.772 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.772 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.772
2025-07-02 04:52:31.772 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.772 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.772 alo = 104, ahi = 1101
2025-07-02 04:52:31.772 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.772 blo = 104, bhi = 1101
2025-07-02 04:52:31.772
2025-07-02 04:52:31.772 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.772 g = []
2025-07-02 04:52:31.772 if alo < ahi:
2025-07-02 04:52:31.772 if blo < bhi:
2025-07-02 04:52:31.772 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.772 else:
2025-07-02 04:52:31.773 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.773 elif blo < bhi:
2025-07-02 04:52:31.773 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.773
2025-07-02 04:52:31.773 > yield from g
2025-07-02 04:52:31.773
2025-07-02 04:52:31.773 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.773 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.773
2025-07-02 04:52:31.773 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.773 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.773 alo = 104, ahi = 1101
2025-07-02 04:52:31.773 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.773 blo = 104, bhi = 1101
2025-07-02 04:52:31.773
2025-07-02 04:52:31.773 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.773 r"""
2025-07-02 04:52:31.773 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.773 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.773 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.773 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.774
2025-07-02 04:52:31.774 Example:
2025-07-02 04:52:31.774
2025-07-02 04:52:31.774 >>> d = Differ()
2025-07-02 04:52:31.774 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.774 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.774 >>> print(''.join(results), end="")
2025-07-02 04:52:31.774 - abcDefghiJkl
2025-07-02 04:52:31.774 + abcdefGhijkl
2025-07-02 04:52:31.774 """
2025-07-02 04:52:31.774
2025-07-02 04:52:31.774 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.774 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.774 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.774 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.774 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.774
2025-07-02 04:52:31.774 # search for the pair that matches best without being identical
2025-07-02 04:52:31.774 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.774 # on junk -- unless we have to)
2025-07-02 04:52:31.775 for j in range(blo, bhi):
2025-07-02 04:52:31.775 bj = b[j]
2025-07-02 04:52:31.775 cruncher.set_seq2(bj)
2025-07-02 04:52:31.775 for i in range(alo, ahi):
2025-07-02 04:52:31.775 ai = a[i]
2025-07-02 04:52:31.775 if ai == bj:
2025-07-02 04:52:31.775 if eqi is None:
2025-07-02 04:52:31.775 eqi, eqj = i, j
2025-07-02 04:52:31.775 continue
2025-07-02 04:52:31.775 cruncher.set_seq1(ai)
2025-07-02 04:52:31.775 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.775 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.775 # compares by a factor of 3.
2025-07-02 04:52:31.775 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.775 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.775 # of the computation is cached by cruncher
2025-07-02 04:52:31.775 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.775 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.775 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.775 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.775 if best_ratio < cutoff:
2025-07-02 04:52:31.776 # no non-identical "pretty close" pair
2025-07-02 04:52:31.776 if eqi is None:
2025-07-02 04:52:31.776 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.776 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.776 return
2025-07-02 04:52:31.776 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.776 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.776 else:
2025-07-02 04:52:31.776 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.776 eqi = None
2025-07-02 04:52:31.776
2025-07-02 04:52:31.776 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.776 # identical
2025-07-02 04:52:31.776
2025-07-02 04:52:31.776 # pump out diffs from before the synch point
2025-07-02 04:52:31.776 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.776
2025-07-02 04:52:31.776 # do intraline marking on the synch pair
2025-07-02 04:52:31.776 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.776 if eqi is None:
2025-07-02 04:52:31.776 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.776 atags = btags = ""
2025-07-02 04:52:31.777 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.777 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.777 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.777 if tag == 'replace':
2025-07-02 04:52:31.777 atags += '^' * la
2025-07-02 04:52:31.777 btags += '^' * lb
2025-07-02 04:52:31.777 elif tag == 'delete':
2025-07-02 04:52:31.777 atags += '-' * la
2025-07-02 04:52:31.777 elif tag == 'insert':
2025-07-02 04:52:31.777 btags += '+' * lb
2025-07-02 04:52:31.777 elif tag == 'equal':
2025-07-02 04:52:31.777 atags += ' ' * la
2025-07-02 04:52:31.777 btags += ' ' * lb
2025-07-02 04:52:31.777 else:
2025-07-02 04:52:31.777 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.777 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.777 else:
2025-07-02 04:52:31.777 # the synch pair is identical
2025-07-02 04:52:31.777 yield ' ' + aelt
2025-07-02 04:52:31.777
2025-07-02 04:52:31.778 # pump out diffs from after the synch point
2025-07-02 04:52:31.778 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.778
2025-07-02 04:52:31.778 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.778 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.778
2025-07-02 04:52:31.778 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.778 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.778 alo = 105, ahi = 1101
2025-07-02 04:52:31.778 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.778 blo = 105, bhi = 1101
2025-07-02 04:52:31.778
2025-07-02 04:52:31.778 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.778 g = []
2025-07-02 04:52:31.778 if alo < ahi:
2025-07-02 04:52:31.778 if blo < bhi:
2025-07-02 04:52:31.778 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.778 else:
2025-07-02 04:52:31.778 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.778 elif blo < bhi:
2025-07-02 04:52:31.779 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.779
2025-07-02 04:52:31.779 > yield from g
2025-07-02 04:52:31.779
2025-07-02 04:52:31.779 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.779 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.779
2025-07-02 04:52:31.779 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.779 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.779 alo = 105, ahi = 1101
2025-07-02 04:52:31.779 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.779 blo = 105, bhi = 1101
2025-07-02 04:52:31.779
2025-07-02 04:52:31.779 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.779 r"""
2025-07-02 04:52:31.779 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.779 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.779 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.779 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.779
2025-07-02 04:52:31.779 Example:
2025-07-02 04:52:31.780
2025-07-02 04:52:31.780 >>> d = Differ()
2025-07-02 04:52:31.780 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.780 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.780 >>> print(''.join(results), end="")
2025-07-02 04:52:31.780 - abcDefghiJkl
2025-07-02 04:52:31.780 + abcdefGhijkl
2025-07-02 04:52:31.780 """
2025-07-02 04:52:31.780
2025-07-02 04:52:31.780 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.780 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.780 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.780 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.780 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.780
2025-07-02 04:52:31.780 # search for the pair that matches best without being identical
2025-07-02 04:52:31.780 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.780 # on junk -- unless we have to)
2025-07-02 04:52:31.780 for j in range(blo, bhi):
2025-07-02 04:52:31.780 bj = b[j]
2025-07-02 04:52:31.781 cruncher.set_seq2(bj)
2025-07-02 04:52:31.781 for i in range(alo, ahi):
2025-07-02 04:52:31.781 ai = a[i]
2025-07-02 04:52:31.781 if ai == bj:
2025-07-02 04:52:31.781 if eqi is None:
2025-07-02 04:52:31.781 eqi, eqj = i, j
2025-07-02 04:52:31.781 continue
2025-07-02 04:52:31.781 cruncher.set_seq1(ai)
2025-07-02 04:52:31.781 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.781 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.781 # compares by a factor of 3.
2025-07-02 04:52:31.781 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.781 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.781 # of the computation is cached by cruncher
2025-07-02 04:52:31.781 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.781 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.781 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.781 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.781 if best_ratio < cutoff:
2025-07-02 04:52:31.781 # no non-identical "pretty close" pair
2025-07-02 04:52:31.781 if eqi is None:
2025-07-02 04:52:31.782 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.782 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.782 return
2025-07-02 04:52:31.782 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.782 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.782 else:
2025-07-02 04:52:31.782 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.782 eqi = None
2025-07-02 04:52:31.782
2025-07-02 04:52:31.782 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.782 # identical
2025-07-02 04:52:31.782
2025-07-02 04:52:31.782 # pump out diffs from before the synch point
2025-07-02 04:52:31.782 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.782
2025-07-02 04:52:31.782 # do intraline marking on the synch pair
2025-07-02 04:52:31.782 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.782 if eqi is None:
2025-07-02 04:52:31.782 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.782 atags = btags = ""
2025-07-02 04:52:31.782 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.783 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.783 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.783 if tag == 'replace':
2025-07-02 04:52:31.783 atags += '^' * la
2025-07-02 04:52:31.783 btags += '^' * lb
2025-07-02 04:52:31.783 elif tag == 'delete':
2025-07-02 04:52:31.783 atags += '-' * la
2025-07-02 04:52:31.783 elif tag == 'insert':
2025-07-02 04:52:31.783 btags += '+' * lb
2025-07-02 04:52:31.783 elif tag == 'equal':
2025-07-02 04:52:31.783 atags += ' ' * la
2025-07-02 04:52:31.783 btags += ' ' * lb
2025-07-02 04:52:31.783 else:
2025-07-02 04:52:31.783 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.783 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.783 else:
2025-07-02 04:52:31.783 # the synch pair is identical
2025-07-02 04:52:31.783 yield ' ' + aelt
2025-07-02 04:52:31.783
2025-07-02 04:52:31.783 # pump out diffs from after the synch point
2025-07-02 04:52:31.783 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.783
2025-07-02 04:52:31.784 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.784 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.784
2025-07-02 04:52:31.784 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.784 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.784 alo = 106, ahi = 1101
2025-07-02 04:52:31.784 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.784 blo = 106, bhi = 1101
2025-07-02 04:52:31.784
2025-07-02 04:52:31.784 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.784 g = []
2025-07-02 04:52:31.784 if alo < ahi:
2025-07-02 04:52:31.784 if blo < bhi:
2025-07-02 04:52:31.784 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.784 else:
2025-07-02 04:52:31.784 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.784 elif blo < bhi:
2025-07-02 04:52:31.784 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.784
2025-07-02 04:52:31.784 > yield from g
2025-07-02 04:52:31.784
2025-07-02 04:52:31.785 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.785 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.785
2025-07-02 04:52:31.785 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.785 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.785 alo = 106, ahi = 1101
2025-07-02 04:52:31.785 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.785 blo = 106, bhi = 1101
2025-07-02 04:52:31.785
2025-07-02 04:52:31.785 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.785 r"""
2025-07-02 04:52:31.785 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.785 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.785 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.785 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.785
2025-07-02 04:52:31.785 Example:
2025-07-02 04:52:31.785
2025-07-02 04:52:31.785 >>> d = Differ()
2025-07-02 04:52:31.785 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.786 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.786 >>> print(''.join(results), end="")
2025-07-02 04:52:31.786 - abcDefghiJkl
2025-07-02 04:52:31.786 + abcdefGhijkl
2025-07-02 04:52:31.786 """
2025-07-02 04:52:31.786
2025-07-02 04:52:31.786 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.786 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.786 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.786 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.786 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.786
2025-07-02 04:52:31.786 # search for the pair that matches best without being identical
2025-07-02 04:52:31.786 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.786 # on junk -- unless we have to)
2025-07-02 04:52:31.786 for j in range(blo, bhi):
2025-07-02 04:52:31.786 bj = b[j]
2025-07-02 04:52:31.786 cruncher.set_seq2(bj)
2025-07-02 04:52:31.787 for i in range(alo, ahi):
2025-07-02 04:52:31.787 ai = a[i]
2025-07-02 04:52:31.787 if ai == bj:
2025-07-02 04:52:31.787 if eqi is None:
2025-07-02 04:52:31.787 eqi, eqj = i, j
2025-07-02 04:52:31.787 continue
2025-07-02 04:52:31.787 cruncher.set_seq1(ai)
2025-07-02 04:52:31.787 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.787 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.787 # compares by a factor of 3.
2025-07-02 04:52:31.787 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.787 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.787 # of the computation is cached by cruncher
2025-07-02 04:52:31.787 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.787 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.787 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.787 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.787 if best_ratio < cutoff:
2025-07-02 04:52:31.787 # no non-identical "pretty close" pair
2025-07-02 04:52:31.787 if eqi is None:
2025-07-02 04:52:31.787 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.788 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.788 return
2025-07-02 04:52:31.788 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.788 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.788 else:
2025-07-02 04:52:31.788 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.788 eqi = None
2025-07-02 04:52:31.788
2025-07-02 04:52:31.788 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.788 # identical
2025-07-02 04:52:31.788
2025-07-02 04:52:31.788 # pump out diffs from before the synch point
2025-07-02 04:52:31.788 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.788
2025-07-02 04:52:31.788 # do intraline marking on the synch pair
2025-07-02 04:52:31.788 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.788 if eqi is None:
2025-07-02 04:52:31.788 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.788 atags = btags = ""
2025-07-02 04:52:31.788 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.788 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.788 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.789 if tag == 'replace':
2025-07-02 04:52:31.789 atags += '^' * la
2025-07-02 04:52:31.789 btags += '^' * lb
2025-07-02 04:52:31.789 elif tag == 'delete':
2025-07-02 04:52:31.789 atags += '-' * la
2025-07-02 04:52:31.789 elif tag == 'insert':
2025-07-02 04:52:31.789 btags += '+' * lb
2025-07-02 04:52:31.789 elif tag == 'equal':
2025-07-02 04:52:31.789 atags += ' ' * la
2025-07-02 04:52:31.789 btags += ' ' * lb
2025-07-02 04:52:31.789 else:
2025-07-02 04:52:31.789 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.789 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.789 else:
2025-07-02 04:52:31.789 # the synch pair is identical
2025-07-02 04:52:31.789 yield ' ' + aelt
2025-07-02 04:52:31.789
2025-07-02 04:52:31.789 # pump out diffs from after the synch point
2025-07-02 04:52:31.789 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.789
2025-07-02 04:52:31.789 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.790 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.790
2025-07-02 04:52:31.790 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.790 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.790 alo = 107, ahi = 1101
2025-07-02 04:52:31.790 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.790 blo = 107, bhi = 1101
2025-07-02 04:52:31.790
2025-07-02 04:52:31.790 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.790 g = []
2025-07-02 04:52:31.790 if alo < ahi:
2025-07-02 04:52:31.790 if blo < bhi:
2025-07-02 04:52:31.790 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.790 else:
2025-07-02 04:52:31.790 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.790 elif blo < bhi:
2025-07-02 04:52:31.790 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.790
2025-07-02 04:52:31.790 > yield from g
2025-07-02 04:52:31.790
2025-07-02 04:52:31.790 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.790 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.791
2025-07-02 04:52:31.791 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.791 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.791 alo = 107, ahi = 1101
2025-07-02 04:52:31.791 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.791 blo = 107, bhi = 1101
2025-07-02 04:52:31.791
2025-07-02 04:52:31.791 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.791 r"""
2025-07-02 04:52:31.791 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.791 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.791 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.791 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.791
2025-07-02 04:52:31.791 Example:
2025-07-02 04:52:31.791
2025-07-02 04:52:31.791 >>> d = Differ()
2025-07-02 04:52:31.791 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.791 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.791 >>> print(''.join(results), end="")
2025-07-02 04:52:31.791 - abcDefghiJkl
2025-07-02 04:52:31.792 + abcdefGhijkl
2025-07-02 04:52:31.792 """
2025-07-02 04:52:31.792
2025-07-02 04:52:31.792 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.792 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.792 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.792 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.792 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.792
2025-07-02 04:52:31.792 # search for the pair that matches best without being identical
2025-07-02 04:52:31.792 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.792 # on junk -- unless we have to)
2025-07-02 04:52:31.792 for j in range(blo, bhi):
2025-07-02 04:52:31.792 bj = b[j]
2025-07-02 04:52:31.792 cruncher.set_seq2(bj)
2025-07-02 04:52:31.792 for i in range(alo, ahi):
2025-07-02 04:52:31.792 ai = a[i]
2025-07-02 04:52:31.792 if ai == bj:
2025-07-02 04:52:31.792 if eqi is None:
2025-07-02 04:52:31.793 eqi, eqj = i, j
2025-07-02 04:52:31.793 continue
2025-07-02 04:52:31.793 cruncher.set_seq1(ai)
2025-07-02 04:52:31.793 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.793 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.793 # compares by a factor of 3.
2025-07-02 04:52:31.793 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.793 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.793 # of the computation is cached by cruncher
2025-07-02 04:52:31.793 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.793 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.793 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.793 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.793 if best_ratio < cutoff:
2025-07-02 04:52:31.793 # no non-identical "pretty close" pair
2025-07-02 04:52:31.793 if eqi is None:
2025-07-02 04:52:31.793 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.793 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.793 return
2025-07-02 04:52:31.793 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.794 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.794 else:
2025-07-02 04:52:31.794 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.794 eqi = None
2025-07-02 04:52:31.794
2025-07-02 04:52:31.794 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.794 # identical
2025-07-02 04:52:31.794
2025-07-02 04:52:31.794 # pump out diffs from before the synch point
2025-07-02 04:52:31.794 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.794
2025-07-02 04:52:31.794 # do intraline marking on the synch pair
2025-07-02 04:52:31.794 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.794 if eqi is None:
2025-07-02 04:52:31.794 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.794 atags = btags = ""
2025-07-02 04:52:31.794 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.794 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.794 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.794 if tag == 'replace':
2025-07-02 04:52:31.794 atags += '^' * la
2025-07-02 04:52:31.795 btags += '^' * lb
2025-07-02 04:52:31.795 elif tag == 'delete':
2025-07-02 04:52:31.795 atags += '-' * la
2025-07-02 04:52:31.795 elif tag == 'insert':
2025-07-02 04:52:31.795 btags += '+' * lb
2025-07-02 04:52:31.795 elif tag == 'equal':
2025-07-02 04:52:31.795 atags += ' ' * la
2025-07-02 04:52:31.795 btags += ' ' * lb
2025-07-02 04:52:31.795 else:
2025-07-02 04:52:31.795 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.795 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.795 else:
2025-07-02 04:52:31.795 # the synch pair is identical
2025-07-02 04:52:31.795 yield ' ' + aelt
2025-07-02 04:52:31.795
2025-07-02 04:52:31.795 # pump out diffs from after the synch point
2025-07-02 04:52:31.795 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.795
2025-07-02 04:52:31.795 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.795 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.795
2025-07-02 04:52:31.796 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.796 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.796 alo = 108, ahi = 1101
2025-07-02 04:52:31.796 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.796 blo = 108, bhi = 1101
2025-07-02 04:52:31.796
2025-07-02 04:52:31.796 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.796 g = []
2025-07-02 04:52:31.796 if alo < ahi:
2025-07-02 04:52:31.796 if blo < bhi:
2025-07-02 04:52:31.796 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.796 else:
2025-07-02 04:52:31.796 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.796 elif blo < bhi:
2025-07-02 04:52:31.796 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.796
2025-07-02 04:52:31.796 > yield from g
2025-07-02 04:52:31.796
2025-07-02 04:52:31.796 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.796 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.796
2025-07-02 04:52:31.797 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.797 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.797 alo = 108, ahi = 1101
2025-07-02 04:52:31.797 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.797 blo = 108, bhi = 1101
2025-07-02 04:52:31.797
2025-07-02 04:52:31.797 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.797 r"""
2025-07-02 04:52:31.797 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.797 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.797 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.797 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.797
2025-07-02 04:52:31.797 Example:
2025-07-02 04:52:31.797
2025-07-02 04:52:31.797 >>> d = Differ()
2025-07-02 04:52:31.797 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.797 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.797 >>> print(''.join(results), end="")
2025-07-02 04:52:31.798 - abcDefghiJkl
2025-07-02 04:52:31.798 + abcdefGhijkl
2025-07-02 04:52:31.798 """
2025-07-02 04:52:31.798
2025-07-02 04:52:31.798 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.798 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.798 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.798 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.798 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.798
2025-07-02 04:52:31.798 # search for the pair that matches best without being identical
2025-07-02 04:52:31.798 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.798 # on junk -- unless we have to)
2025-07-02 04:52:31.798 for j in range(blo, bhi):
2025-07-02 04:52:31.798 bj = b[j]
2025-07-02 04:52:31.798 cruncher.set_seq2(bj)
2025-07-02 04:52:31.798 for i in range(alo, ahi):
2025-07-02 04:52:31.798 ai = a[i]
2025-07-02 04:52:31.798 if ai == bj:
2025-07-02 04:52:31.799 if eqi is None:
2025-07-02 04:52:31.799 eqi, eqj = i, j
2025-07-02 04:52:31.799 continue
2025-07-02 04:52:31.799 cruncher.set_seq1(ai)
2025-07-02 04:52:31.799 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.799 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.799 # compares by a factor of 3.
2025-07-02 04:52:31.799 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.799 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.799 # of the computation is cached by cruncher
2025-07-02 04:52:31.799 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.799 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.799 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.799 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.799 if best_ratio < cutoff:
2025-07-02 04:52:31.799 # no non-identical "pretty close" pair
2025-07-02 04:52:31.799 if eqi is None:
2025-07-02 04:52:31.799 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.799 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.799 return
2025-07-02 04:52:31.800 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.800 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.800 else:
2025-07-02 04:52:31.800 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.800 eqi = None
2025-07-02 04:52:31.800
2025-07-02 04:52:31.800 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.800 # identical
2025-07-02 04:52:31.800
2025-07-02 04:52:31.800 # pump out diffs from before the synch point
2025-07-02 04:52:31.800 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.800
2025-07-02 04:52:31.800 # do intraline marking on the synch pair
2025-07-02 04:52:31.800 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.800 if eqi is None:
2025-07-02 04:52:31.800 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.800 atags = btags = ""
2025-07-02 04:52:31.800 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.800 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.800 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.800 if tag == 'replace':
2025-07-02 04:52:31.801 atags += '^' * la
2025-07-02 04:52:31.801 btags += '^' * lb
2025-07-02 04:52:31.801 elif tag == 'delete':
2025-07-02 04:52:31.801 atags += '-' * la
2025-07-02 04:52:31.801 elif tag == 'insert':
2025-07-02 04:52:31.801 btags += '+' * lb
2025-07-02 04:52:31.801 elif tag == 'equal':
2025-07-02 04:52:31.801 atags += ' ' * la
2025-07-02 04:52:31.801 btags += ' ' * lb
2025-07-02 04:52:31.801 else:
2025-07-02 04:52:31.801 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.801 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.801 else:
2025-07-02 04:52:31.801 # the synch pair is identical
2025-07-02 04:52:31.801 yield ' ' + aelt
2025-07-02 04:52:31.801
2025-07-02 04:52:31.801 # pump out diffs from after the synch point
2025-07-02 04:52:31.801 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.801
2025-07-02 04:52:31.801 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.802 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.802
2025-07-02 04:52:31.802 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.802 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.802 alo = 109, ahi = 1101
2025-07-02 04:52:31.802 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.802 blo = 109, bhi = 1101
2025-07-02 04:52:31.802
2025-07-02 04:52:31.802 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.802 g = []
2025-07-02 04:52:31.802 if alo < ahi:
2025-07-02 04:52:31.802 if blo < bhi:
2025-07-02 04:52:31.802 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.802 else:
2025-07-02 04:52:31.802 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.802 elif blo < bhi:
2025-07-02 04:52:31.802 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.802
2025-07-02 04:52:31.802 > yield from g
2025-07-02 04:52:31.803
2025-07-02 04:52:31.803 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.803 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.803
2025-07-02 04:52:31.803 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.803 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.803 alo = 109, ahi = 1101
2025-07-02 04:52:31.803 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.803 blo = 109, bhi = 1101
2025-07-02 04:52:31.803
2025-07-02 04:52:31.803 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.803 r"""
2025-07-02 04:52:31.803 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.803 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.803 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.803 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.803
2025-07-02 04:52:31.803 Example:
2025-07-02 04:52:31.803
2025-07-02 04:52:31.803 >>> d = Differ()
2025-07-02 04:52:31.804 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.804 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.804 >>> print(''.join(results), end="")
2025-07-02 04:52:31.804 - abcDefghiJkl
2025-07-02 04:52:31.804 + abcdefGhijkl
2025-07-02 04:52:31.804 """
2025-07-02 04:52:31.804
2025-07-02 04:52:31.804 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.804 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.804 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.804 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.804 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.804
2025-07-02 04:52:31.804 # search for the pair that matches best without being identical
2025-07-02 04:52:31.804 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.804 # on junk -- unless we have to)
2025-07-02 04:52:31.804 for j in range(blo, bhi):
2025-07-02 04:52:31.804 bj = b[j]
2025-07-02 04:52:31.804 cruncher.set_seq2(bj)
2025-07-02 04:52:31.805 for i in range(alo, ahi):
2025-07-02 04:52:31.805 ai = a[i]
2025-07-02 04:52:31.805 if ai == bj:
2025-07-02 04:52:31.805 if eqi is None:
2025-07-02 04:52:31.805 eqi, eqj = i, j
2025-07-02 04:52:31.805 continue
2025-07-02 04:52:31.805 cruncher.set_seq1(ai)
2025-07-02 04:52:31.805 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.805 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.805 # compares by a factor of 3.
2025-07-02 04:52:31.805 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.805 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.805 # of the computation is cached by cruncher
2025-07-02 04:52:31.805 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.805 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.805 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.805 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.805 if best_ratio < cutoff:
2025-07-02 04:52:31.805 # no non-identical "pretty close" pair
2025-07-02 04:52:31.805 if eqi is None:
2025-07-02 04:52:31.805 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.806 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.806 return
2025-07-02 04:52:31.806 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.806 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.806 else:
2025-07-02 04:52:31.806 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.806 eqi = None
2025-07-02 04:52:31.806
2025-07-02 04:52:31.806 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.806 # identical
2025-07-02 04:52:31.806
2025-07-02 04:52:31.806 # pump out diffs from before the synch point
2025-07-02 04:52:31.806 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.806
2025-07-02 04:52:31.806 # do intraline marking on the synch pair
2025-07-02 04:52:31.806 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.806 if eqi is None:
2025-07-02 04:52:31.806 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.806 atags = btags = ""
2025-07-02 04:52:31.806 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.806 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.807 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.807 if tag == 'replace':
2025-07-02 04:52:31.807 atags += '^' * la
2025-07-02 04:52:31.807 btags += '^' * lb
2025-07-02 04:52:31.807 elif tag == 'delete':
2025-07-02 04:52:31.807 atags += '-' * la
2025-07-02 04:52:31.807 elif tag == 'insert':
2025-07-02 04:52:31.807 btags += '+' * lb
2025-07-02 04:52:31.807 elif tag == 'equal':
2025-07-02 04:52:31.807 atags += ' ' * la
2025-07-02 04:52:31.807 btags += ' ' * lb
2025-07-02 04:52:31.807 else:
2025-07-02 04:52:31.807 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.807 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.807 else:
2025-07-02 04:52:31.807 # the synch pair is identical
2025-07-02 04:52:31.807 yield ' ' + aelt
2025-07-02 04:52:31.807
2025-07-02 04:52:31.807 # pump out diffs from after the synch point
2025-07-02 04:52:31.807 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.808
2025-07-02 04:52:31.808 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.808 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.808
2025-07-02 04:52:31.808 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.808 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.808 alo = 110, ahi = 1101
2025-07-02 04:52:31.808 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.808 blo = 110, bhi = 1101
2025-07-02 04:52:31.808
2025-07-02 04:52:31.808 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.808 g = []
2025-07-02 04:52:31.808 if alo < ahi:
2025-07-02 04:52:31.808 if blo < bhi:
2025-07-02 04:52:31.808 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.808 else:
2025-07-02 04:52:31.808 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.808 elif blo < bhi:
2025-07-02 04:52:31.808 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.808
2025-07-02 04:52:31.808 > yield from g
2025-07-02 04:52:31.809
2025-07-02 04:52:31.809 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.809 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.809
2025-07-02 04:52:31.809 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.809 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.809 alo = 110, ahi = 1101
2025-07-02 04:52:31.809 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.809 blo = 110, bhi = 1101
2025-07-02 04:52:31.809
2025-07-02 04:52:31.809 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.809 r"""
2025-07-02 04:52:31.809 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.809 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.809 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.809 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.809
2025-07-02 04:52:31.809 Example:
2025-07-02 04:52:31.809
2025-07-02 04:52:31.809 >>> d = Differ()
2025-07-02 04:52:31.810 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.810 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.810 >>> print(''.join(results), end="")
2025-07-02 04:52:31.810 - abcDefghiJkl
2025-07-02 04:52:31.810 + abcdefGhijkl
2025-07-02 04:52:31.810 """
2025-07-02 04:52:31.810
2025-07-02 04:52:31.810 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.810 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.810 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.810 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.810 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.810
2025-07-02 04:52:31.810 # search for the pair that matches best without being identical
2025-07-02 04:52:31.810 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.810 # on junk -- unless we have to)
2025-07-02 04:52:31.810 for j in range(blo, bhi):
2025-07-02 04:52:31.810 bj = b[j]
2025-07-02 04:52:31.811 cruncher.set_seq2(bj)
2025-07-02 04:52:31.811 for i in range(alo, ahi):
2025-07-02 04:52:31.811 ai = a[i]
2025-07-02 04:52:31.811 if ai == bj:
2025-07-02 04:52:31.811 if eqi is None:
2025-07-02 04:52:31.811 eqi, eqj = i, j
2025-07-02 04:52:31.811 continue
2025-07-02 04:52:31.811 cruncher.set_seq1(ai)
2025-07-02 04:52:31.811 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.811 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.811 # compares by a factor of 3.
2025-07-02 04:52:31.811 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.811 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.811 # of the computation is cached by cruncher
2025-07-02 04:52:31.811 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.811 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.811 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.811 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.811 if best_ratio < cutoff:
2025-07-02 04:52:31.811 # no non-identical "pretty close" pair
2025-07-02 04:52:31.811 if eqi is None:
2025-07-02 04:52:31.812 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.812 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.812 return
2025-07-02 04:52:31.812 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.812 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.812 else:
2025-07-02 04:52:31.812 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.812 eqi = None
2025-07-02 04:52:31.812
2025-07-02 04:52:31.812 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.812 # identical
2025-07-02 04:52:31.812
2025-07-02 04:52:31.812 # pump out diffs from before the synch point
2025-07-02 04:52:31.812 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.812
2025-07-02 04:52:31.812 # do intraline marking on the synch pair
2025-07-02 04:52:31.812 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.812 if eqi is None:
2025-07-02 04:52:31.812 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.812 atags = btags = ""
2025-07-02 04:52:31.812 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.813 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.813 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.813 if tag == 'replace':
2025-07-02 04:52:31.813 atags += '^' * la
2025-07-02 04:52:31.813 btags += '^' * lb
2025-07-02 04:52:31.813 elif tag == 'delete':
2025-07-02 04:52:31.813 atags += '-' * la
2025-07-02 04:52:31.813 elif tag == 'insert':
2025-07-02 04:52:31.813 btags += '+' * lb
2025-07-02 04:52:31.813 elif tag == 'equal':
2025-07-02 04:52:31.813 atags += ' ' * la
2025-07-02 04:52:31.813 btags += ' ' * lb
2025-07-02 04:52:31.813 else:
2025-07-02 04:52:31.813 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.813 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.813 else:
2025-07-02 04:52:31.813 # the synch pair is identical
2025-07-02 04:52:31.813 yield ' ' + aelt
2025-07-02 04:52:31.813
2025-07-02 04:52:31.813 # pump out diffs from after the synch point
2025-07-02 04:52:31.813 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.814
2025-07-02 04:52:31.814 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.814 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.814
2025-07-02 04:52:31.814 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.814 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.814 alo = 111, ahi = 1101
2025-07-02 04:52:31.814 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.814 blo = 111, bhi = 1101
2025-07-02 04:52:31.814
2025-07-02 04:52:31.814 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.814 g = []
2025-07-02 04:52:31.814 if alo < ahi:
2025-07-02 04:52:31.814 if blo < bhi:
2025-07-02 04:52:31.814 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.814 else:
2025-07-02 04:52:31.814 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.814 elif blo < bhi:
2025-07-02 04:52:31.814 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.814
2025-07-02 04:52:31.814 > yield from g
2025-07-02 04:52:31.814
2025-07-02 04:52:31.815 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.815 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.815
2025-07-02 04:52:31.815 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.815 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.815 alo = 111, ahi = 1101
2025-07-02 04:52:31.815 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.815 blo = 111, bhi = 1101
2025-07-02 04:52:31.815
2025-07-02 04:52:31.815 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.815 r"""
2025-07-02 04:52:31.815 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.815 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.815 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.815 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.815
2025-07-02 04:52:31.815 Example:
2025-07-02 04:52:31.815
2025-07-02 04:52:31.815 >>> d = Differ()
2025-07-02 04:52:31.815 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.815 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.816 >>> print(''.join(results), end="")
2025-07-02 04:52:31.816 - abcDefghiJkl
2025-07-02 04:52:31.816 + abcdefGhijkl
2025-07-02 04:52:31.816 """
2025-07-02 04:52:31.816
2025-07-02 04:52:31.816 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.816 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.816 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.816 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.816 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.816
2025-07-02 04:52:31.816 # search for the pair that matches best without being identical
2025-07-02 04:52:31.816 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.816 # on junk -- unless we have to)
2025-07-02 04:52:31.816 for j in range(blo, bhi):
2025-07-02 04:52:31.816 bj = b[j]
2025-07-02 04:52:31.816 cruncher.set_seq2(bj)
2025-07-02 04:52:31.816 for i in range(alo, ahi):
2025-07-02 04:52:31.816 ai = a[i]
2025-07-02 04:52:31.817 if ai == bj:
2025-07-02 04:52:31.817 if eqi is None:
2025-07-02 04:52:31.817 eqi, eqj = i, j
2025-07-02 04:52:31.817 continue
2025-07-02 04:52:31.817 cruncher.set_seq1(ai)
2025-07-02 04:52:31.817 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.817 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.817 # compares by a factor of 3.
2025-07-02 04:52:31.817 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.817 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.817 # of the computation is cached by cruncher
2025-07-02 04:52:31.817 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.817 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.817 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.817 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.817 if best_ratio < cutoff:
2025-07-02 04:52:31.817 # no non-identical "pretty close" pair
2025-07-02 04:52:31.817 if eqi is None:
2025-07-02 04:52:31.817 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.817 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.817 return
2025-07-02 04:52:31.817 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.818 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.818 else:
2025-07-02 04:52:31.818 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.818 eqi = None
2025-07-02 04:52:31.818
2025-07-02 04:52:31.818 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.818 # identical
2025-07-02 04:52:31.818
2025-07-02 04:52:31.818 # pump out diffs from before the synch point
2025-07-02 04:52:31.818 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.818
2025-07-02 04:52:31.818 # do intraline marking on the synch pair
2025-07-02 04:52:31.818 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.818 if eqi is None:
2025-07-02 04:52:31.818 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.818 atags = btags = ""
2025-07-02 04:52:31.818 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.818 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.819 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.819 if tag == 'replace':
2025-07-02 04:52:31.819 atags += '^' * la
2025-07-02 04:52:31.819 btags += '^' * lb
2025-07-02 04:52:31.819 elif tag == 'delete':
2025-07-02 04:52:31.819 atags += '-' * la
2025-07-02 04:52:31.819 elif tag == 'insert':
2025-07-02 04:52:31.819 btags += '+' * lb
2025-07-02 04:52:31.819 elif tag == 'equal':
2025-07-02 04:52:31.819 atags += ' ' * la
2025-07-02 04:52:31.819 btags += ' ' * lb
2025-07-02 04:52:31.819 else:
2025-07-02 04:52:31.819 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.819 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.819 else:
2025-07-02 04:52:31.819 # the synch pair is identical
2025-07-02 04:52:31.819 yield ' ' + aelt
2025-07-02 04:52:31.819
2025-07-02 04:52:31.819 # pump out diffs from after the synch point
2025-07-02 04:52:31.819 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.820
2025-07-02 04:52:31.820 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.820 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.820
2025-07-02 04:52:31.820 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.820 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.820 alo = 114, ahi = 1101
2025-07-02 04:52:31.820 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.820 blo = 114, bhi = 1101
2025-07-02 04:52:31.820
2025-07-02 04:52:31.820 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.820 g = []
2025-07-02 04:52:31.820 if alo < ahi:
2025-07-02 04:52:31.820 if blo < bhi:
2025-07-02 04:52:31.820 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.820 else:
2025-07-02 04:52:31.820 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.820 elif blo < bhi:
2025-07-02 04:52:31.820 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.820
2025-07-02 04:52:31.821 > yield from g
2025-07-02 04:52:31.821
2025-07-02 04:52:31.821 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.821 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.821
2025-07-02 04:52:31.821 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.821 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.821 alo = 114, ahi = 1101
2025-07-02 04:52:31.821 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.821 blo = 114, bhi = 1101
2025-07-02 04:52:31.821
2025-07-02 04:52:31.821 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.821 r"""
2025-07-02 04:52:31.821 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.821 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.821 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.821 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.821
2025-07-02 04:52:31.821 Example:
2025-07-02 04:52:31.821
2025-07-02 04:52:31.821 >>> d = Differ()
2025-07-02 04:52:31.821 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.822 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.822 >>> print(''.join(results), end="")
2025-07-02 04:52:31.822 - abcDefghiJkl
2025-07-02 04:52:31.822 + abcdefGhijkl
2025-07-02 04:52:31.822 """
2025-07-02 04:52:31.822
2025-07-02 04:52:31.822 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.822 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.822 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.822 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.822 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.822
2025-07-02 04:52:31.822 # search for the pair that matches best without being identical
2025-07-02 04:52:31.822 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.822 # on junk -- unless we have to)
2025-07-02 04:52:31.822 for j in range(blo, bhi):
2025-07-02 04:52:31.822 bj = b[j]
2025-07-02 04:52:31.822 cruncher.set_seq2(bj)
2025-07-02 04:52:31.822 for i in range(alo, ahi):
2025-07-02 04:52:31.823 ai = a[i]
2025-07-02 04:52:31.823 if ai == bj:
2025-07-02 04:52:31.823 if eqi is None:
2025-07-02 04:52:31.823 eqi, eqj = i, j
2025-07-02 04:52:31.823 continue
2025-07-02 04:52:31.823 cruncher.set_seq1(ai)
2025-07-02 04:52:31.823 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.823 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.823 # compares by a factor of 3.
2025-07-02 04:52:31.823 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.823 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.823 # of the computation is cached by cruncher
2025-07-02 04:52:31.823 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.823 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.823 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.823 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.823 if best_ratio < cutoff:
2025-07-02 04:52:31.823 # no non-identical "pretty close" pair
2025-07-02 04:52:31.823 if eqi is None:
2025-07-02 04:52:31.823 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.823 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.824 return
2025-07-02 04:52:31.824 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.824 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.824 else:
2025-07-02 04:52:31.824 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.824 eqi = None
2025-07-02 04:52:31.824
2025-07-02 04:52:31.824 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.824 # identical
2025-07-02 04:52:31.824
2025-07-02 04:52:31.824 # pump out diffs from before the synch point
2025-07-02 04:52:31.824 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.824
2025-07-02 04:52:31.824 # do intraline marking on the synch pair
2025-07-02 04:52:31.824 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.824 if eqi is None:
2025-07-02 04:52:31.824 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.824 atags = btags = ""
2025-07-02 04:52:31.824 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.824 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.824 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.824 if tag == 'replace':
2025-07-02 04:52:31.825 atags += '^' * la
2025-07-02 04:52:31.825 btags += '^' * lb
2025-07-02 04:52:31.825 elif tag == 'delete':
2025-07-02 04:52:31.825 atags += '-' * la
2025-07-02 04:52:31.825 elif tag == 'insert':
2025-07-02 04:52:31.825 btags += '+' * lb
2025-07-02 04:52:31.825 elif tag == 'equal':
2025-07-02 04:52:31.825 atags += ' ' * la
2025-07-02 04:52:31.825 btags += ' ' * lb
2025-07-02 04:52:31.825 else:
2025-07-02 04:52:31.825 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.825 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.825 else:
2025-07-02 04:52:31.825 # the synch pair is identical
2025-07-02 04:52:31.825 yield ' ' + aelt
2025-07-02 04:52:31.825
2025-07-02 04:52:31.825 # pump out diffs from after the synch point
2025-07-02 04:52:31.825 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.825
2025-07-02 04:52:31.825 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.825 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.825
2025-07-02 04:52:31.826 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.826 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.826 alo = 115, ahi = 1101
2025-07-02 04:52:31.826 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.826 blo = 115, bhi = 1101
2025-07-02 04:52:31.826
2025-07-02 04:52:31.826 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.826 g = []
2025-07-02 04:52:31.826 if alo < ahi:
2025-07-02 04:52:31.826 if blo < bhi:
2025-07-02 04:52:31.826 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.826 else:
2025-07-02 04:52:31.826 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.826 elif blo < bhi:
2025-07-02 04:52:31.826 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.826
2025-07-02 04:52:31.826 > yield from g
2025-07-02 04:52:31.826
2025-07-02 04:52:31.826 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.827 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.827
2025-07-02 04:52:31.827 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.827 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.827 alo = 115, ahi = 1101
2025-07-02 04:52:31.827 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.827 blo = 115, bhi = 1101
2025-07-02 04:52:31.827
2025-07-02 04:52:31.827 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.827 r"""
2025-07-02 04:52:31.827 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.827 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.827 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.827 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.827
2025-07-02 04:52:31.827 Example:
2025-07-02 04:52:31.827
2025-07-02 04:52:31.827 >>> d = Differ()
2025-07-02 04:52:31.827 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.827 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.828 >>> print(''.join(results), end="")
2025-07-02 04:52:31.828 - abcDefghiJkl
2025-07-02 04:52:31.828 + abcdefGhijkl
2025-07-02 04:52:31.828 """
2025-07-02 04:52:31.828
2025-07-02 04:52:31.828 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.828 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.828 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.828 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.828 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.828
2025-07-02 04:52:31.828 # search for the pair that matches best without being identical
2025-07-02 04:52:31.828 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.828 # on junk -- unless we have to)
2025-07-02 04:52:31.828 for j in range(blo, bhi):
2025-07-02 04:52:31.828 bj = b[j]
2025-07-02 04:52:31.828 cruncher.set_seq2(bj)
2025-07-02 04:52:31.828 for i in range(alo, ahi):
2025-07-02 04:52:31.829 ai = a[i]
2025-07-02 04:52:31.829 if ai == bj:
2025-07-02 04:52:31.829 if eqi is None:
2025-07-02 04:52:31.829 eqi, eqj = i, j
2025-07-02 04:52:31.829 continue
2025-07-02 04:52:31.829 cruncher.set_seq1(ai)
2025-07-02 04:52:31.829 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.829 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.829 # compares by a factor of 3.
2025-07-02 04:52:31.829 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.829 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.829 # of the computation is cached by cruncher
2025-07-02 04:52:31.829 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.829 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.829 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.829 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.829 if best_ratio < cutoff:
2025-07-02 04:52:31.829 # no non-identical "pretty close" pair
2025-07-02 04:52:31.829 if eqi is None:
2025-07-02 04:52:31.829 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.829 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.830 return
2025-07-02 04:52:31.830 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.830 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.830 else:
2025-07-02 04:52:31.830 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.830 eqi = None
2025-07-02 04:52:31.830
2025-07-02 04:52:31.830 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.830 # identical
2025-07-02 04:52:31.830
2025-07-02 04:52:31.830 # pump out diffs from before the synch point
2025-07-02 04:52:31.830 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.830
2025-07-02 04:52:31.830 # do intraline marking on the synch pair
2025-07-02 04:52:31.830 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.830 if eqi is None:
2025-07-02 04:52:31.830 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.830 atags = btags = ""
2025-07-02 04:52:31.830 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.830 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.830 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.831 if tag == 'replace':
2025-07-02 04:52:31.831 atags += '^' * la
2025-07-02 04:52:31.831 btags += '^' * lb
2025-07-02 04:52:31.831 elif tag == 'delete':
2025-07-02 04:52:31.831 atags += '-' * la
2025-07-02 04:52:31.831 elif tag == 'insert':
2025-07-02 04:52:31.831 btags += '+' * lb
2025-07-02 04:52:31.831 elif tag == 'equal':
2025-07-02 04:52:31.831 atags += ' ' * la
2025-07-02 04:52:31.831 btags += ' ' * lb
2025-07-02 04:52:31.831 else:
2025-07-02 04:52:31.831 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.831 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.831 else:
2025-07-02 04:52:31.831 # the synch pair is identical
2025-07-02 04:52:31.831 yield ' ' + aelt
2025-07-02 04:52:31.831
2025-07-02 04:52:31.831 # pump out diffs from after the synch point
2025-07-02 04:52:31.831 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.831
2025-07-02 04:52:31.831 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.832 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.832
2025-07-02 04:52:31.832 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.832 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.832 alo = 116, ahi = 1101
2025-07-02 04:52:31.832 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.832 blo = 116, bhi = 1101
2025-07-02 04:52:31.832
2025-07-02 04:52:31.832 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.832 g = []
2025-07-02 04:52:31.832 if alo < ahi:
2025-07-02 04:52:31.832 if blo < bhi:
2025-07-02 04:52:31.832 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.832 else:
2025-07-02 04:52:31.832 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.832 elif blo < bhi:
2025-07-02 04:52:31.832 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.832
2025-07-02 04:52:31.832 > yield from g
2025-07-02 04:52:31.832
2025-07-02 04:52:31.833 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.833 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.833
2025-07-02 04:52:31.833 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.833 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.833 alo = 116, ahi = 1101
2025-07-02 04:52:31.833 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.833 blo = 116, bhi = 1101
2025-07-02 04:52:31.833
2025-07-02 04:52:31.833 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.833 r"""
2025-07-02 04:52:31.833 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.833 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.833 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.833 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.833
2025-07-02 04:52:31.833 Example:
2025-07-02 04:52:31.833
2025-07-02 04:52:31.833 >>> d = Differ()
2025-07-02 04:52:31.833 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.834 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.834 >>> print(''.join(results), end="")
2025-07-02 04:52:31.834 - abcDefghiJkl
2025-07-02 04:52:31.834 + abcdefGhijkl
2025-07-02 04:52:31.834 """
2025-07-02 04:52:31.834
2025-07-02 04:52:31.834 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.834 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.834 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.834 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.834 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.834
2025-07-02 04:52:31.834 # search for the pair that matches best without being identical
2025-07-02 04:52:31.834 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.834 # on junk -- unless we have to)
2025-07-02 04:52:31.834 for j in range(blo, bhi):
2025-07-02 04:52:31.834 bj = b[j]
2025-07-02 04:52:31.835 cruncher.set_seq2(bj)
2025-07-02 04:52:31.835 for i in range(alo, ahi):
2025-07-02 04:52:31.835 ai = a[i]
2025-07-02 04:52:31.835 if ai == bj:
2025-07-02 04:52:31.835 if eqi is None:
2025-07-02 04:52:31.835 eqi, eqj = i, j
2025-07-02 04:52:31.835 continue
2025-07-02 04:52:31.835 cruncher.set_seq1(ai)
2025-07-02 04:52:31.835 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.835 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.835 # compares by a factor of 3.
2025-07-02 04:52:31.835 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.835 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.835 # of the computation is cached by cruncher
2025-07-02 04:52:31.835 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.835 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.835 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.835 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.835 if best_ratio < cutoff:
2025-07-02 04:52:31.836 # no non-identical "pretty close" pair
2025-07-02 04:52:31.836 if eqi is None:
2025-07-02 04:52:31.836 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.836 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.836 return
2025-07-02 04:52:31.836 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.836 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.836 else:
2025-07-02 04:52:31.836 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.836 eqi = None
2025-07-02 04:52:31.836
2025-07-02 04:52:31.836 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.836 # identical
2025-07-02 04:52:31.836
2025-07-02 04:52:31.836 # pump out diffs from before the synch point
2025-07-02 04:52:31.836 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.836
2025-07-02 04:52:31.836 # do intraline marking on the synch pair
2025-07-02 04:52:31.836 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.836 if eqi is None:
2025-07-02 04:52:31.837 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.837 atags = btags = ""
2025-07-02 04:52:31.837 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.837 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.837 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.837 if tag == 'replace':
2025-07-02 04:52:31.837 atags += '^' * la
2025-07-02 04:52:31.837 btags += '^' * lb
2025-07-02 04:52:31.837 elif tag == 'delete':
2025-07-02 04:52:31.837 atags += '-' * la
2025-07-02 04:52:31.837 elif tag == 'insert':
2025-07-02 04:52:31.837 btags += '+' * lb
2025-07-02 04:52:31.837 elif tag == 'equal':
2025-07-02 04:52:31.837 atags += ' ' * la
2025-07-02 04:52:31.837 btags += ' ' * lb
2025-07-02 04:52:31.837 else:
2025-07-02 04:52:31.837 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.837 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.837 else:
2025-07-02 04:52:31.837 # the synch pair is identical
2025-07-02 04:52:31.838 yield ' ' + aelt
2025-07-02 04:52:31.838
2025-07-02 04:52:31.838 # pump out diffs from after the synch point
2025-07-02 04:52:31.838 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.838
2025-07-02 04:52:31.838 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.838 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.838
2025-07-02 04:52:31.838 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.838 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.838 alo = 117, ahi = 1101
2025-07-02 04:52:31.838 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.838 blo = 117, bhi = 1101
2025-07-02 04:52:31.838
2025-07-02 04:52:31.838 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.838 g = []
2025-07-02 04:52:31.838 if alo < ahi:
2025-07-02 04:52:31.838 if blo < bhi:
2025-07-02 04:52:31.838 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.839 else:
2025-07-02 04:52:31.839 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.839 elif blo < bhi:
2025-07-02 04:52:31.839 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.839
2025-07-02 04:52:31.839 > yield from g
2025-07-02 04:52:31.839
2025-07-02 04:52:31.839 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.839 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.839
2025-07-02 04:52:31.839 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.839 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.839 alo = 117, ahi = 1101
2025-07-02 04:52:31.839 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.839 blo = 117, bhi = 1101
2025-07-02 04:52:31.839
2025-07-02 04:52:31.839 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.839 r"""
2025-07-02 04:52:31.839 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.840 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.840 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.840 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.840
2025-07-02 04:52:31.840 Example:
2025-07-02 04:52:31.840
2025-07-02 04:52:31.840 >>> d = Differ()
2025-07-02 04:52:31.840 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.840 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.840 >>> print(''.join(results), end="")
2025-07-02 04:52:31.840 - abcDefghiJkl
2025-07-02 04:52:31.840 + abcdefGhijkl
2025-07-02 04:52:31.840 """
2025-07-02 04:52:31.840
2025-07-02 04:52:31.840 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.840 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.840 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.840 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.841 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.841
2025-07-02 04:52:31.841 # search for the pair that matches best without being identical
2025-07-02 04:52:31.841 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.841 # on junk -- unless we have to)
2025-07-02 04:52:31.841 for j in range(blo, bhi):
2025-07-02 04:52:31.841 bj = b[j]
2025-07-02 04:52:31.841 cruncher.set_seq2(bj)
2025-07-02 04:52:31.841 for i in range(alo, ahi):
2025-07-02 04:52:31.841 ai = a[i]
2025-07-02 04:52:31.841 if ai == bj:
2025-07-02 04:52:31.841 if eqi is None:
2025-07-02 04:52:31.841 eqi, eqj = i, j
2025-07-02 04:52:31.841 continue
2025-07-02 04:52:31.841 cruncher.set_seq1(ai)
2025-07-02 04:52:31.841 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.841 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.841 # compares by a factor of 3.
2025-07-02 04:52:31.841 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.841 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.842 # of the computation is cached by cruncher
2025-07-02 04:52:31.842 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.842 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.842 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.842 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.842 if best_ratio < cutoff:
2025-07-02 04:52:31.842 # no non-identical "pretty close" pair
2025-07-02 04:52:31.842 if eqi is None:
2025-07-02 04:52:31.842 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.842 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.842 return
2025-07-02 04:52:31.842 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.842 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.842 else:
2025-07-02 04:52:31.842 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.842 eqi = None
2025-07-02 04:52:31.842
2025-07-02 04:52:31.843 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.843 # identical
2025-07-02 04:52:31.843
2025-07-02 04:52:31.843 # pump out diffs from before the synch point
2025-07-02 04:52:31.843 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.843
2025-07-02 04:52:31.843 # do intraline marking on the synch pair
2025-07-02 04:52:31.843 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.843 if eqi is None:
2025-07-02 04:52:31.843 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.843 atags = btags = ""
2025-07-02 04:52:31.843 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.843 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.843 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.843 if tag == 'replace':
2025-07-02 04:52:31.843 atags += '^' * la
2025-07-02 04:52:31.843 btags += '^' * lb
2025-07-02 04:52:31.843 elif tag == 'delete':
2025-07-02 04:52:31.843 atags += '-' * la
2025-07-02 04:52:31.843 elif tag == 'insert':
2025-07-02 04:52:31.844 btags += '+' * lb
2025-07-02 04:52:31.844 elif tag == 'equal':
2025-07-02 04:52:31.844 atags += ' ' * la
2025-07-02 04:52:31.844 btags += ' ' * lb
2025-07-02 04:52:31.844 else:
2025-07-02 04:52:31.844 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.844 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.844 else:
2025-07-02 04:52:31.844 # the synch pair is identical
2025-07-02 04:52:31.844 yield ' ' + aelt
2025-07-02 04:52:31.844
2025-07-02 04:52:31.844 # pump out diffs from after the synch point
2025-07-02 04:52:31.844 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.844
2025-07-02 04:52:31.844 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.844 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.844
2025-07-02 04:52:31.844 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.845 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.845 alo = 118, ahi = 1101
2025-07-02 04:52:31.845 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.845 blo = 118, bhi = 1101
2025-07-02 04:52:31.845
2025-07-02 04:52:31.845 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.845 g = []
2025-07-02 04:52:31.845 if alo < ahi:
2025-07-02 04:52:31.845 if blo < bhi:
2025-07-02 04:52:31.845 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.845 else:
2025-07-02 04:52:31.845 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.845 elif blo < bhi:
2025-07-02 04:52:31.845 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.845
2025-07-02 04:52:31.845 > yield from g
2025-07-02 04:52:31.845
2025-07-02 04:52:31.845 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.845 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.845
2025-07-02 04:52:31.846 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.846 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.846 alo = 118, ahi = 1101
2025-07-02 04:52:31.846 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.846 blo = 118, bhi = 1101
2025-07-02 04:52:31.846
2025-07-02 04:52:31.846 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.846 r"""
2025-07-02 04:52:31.846 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.846 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.846 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.846 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.846
2025-07-02 04:52:31.846 Example:
2025-07-02 04:52:31.846
2025-07-02 04:52:31.846 >>> d = Differ()
2025-07-02 04:52:31.846 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.846 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.846 >>> print(''.join(results), end="")
2025-07-02 04:52:31.846 - abcDefghiJkl
2025-07-02 04:52:31.847 + abcdefGhijkl
2025-07-02 04:52:31.847 """
2025-07-02 04:52:31.847
2025-07-02 04:52:31.847 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.847 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.847 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.847 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.847 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.847
2025-07-02 04:52:31.847 # search for the pair that matches best without being identical
2025-07-02 04:52:31.847 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.847 # on junk -- unless we have to)
2025-07-02 04:52:31.847 for j in range(blo, bhi):
2025-07-02 04:52:31.847 bj = b[j]
2025-07-02 04:52:31.847 cruncher.set_seq2(bj)
2025-07-02 04:52:31.847 for i in range(alo, ahi):
2025-07-02 04:52:31.847 ai = a[i]
2025-07-02 04:52:31.847 if ai == bj:
2025-07-02 04:52:31.847 if eqi is None:
2025-07-02 04:52:31.848 eqi, eqj = i, j
2025-07-02 04:52:31.848 continue
2025-07-02 04:52:31.848 cruncher.set_seq1(ai)
2025-07-02 04:52:31.848 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.848 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.848 # compares by a factor of 3.
2025-07-02 04:52:31.848 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.848 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.848 # of the computation is cached by cruncher
2025-07-02 04:52:31.848 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.848 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.848 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.848 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.848 if best_ratio < cutoff:
2025-07-02 04:52:31.848 # no non-identical "pretty close" pair
2025-07-02 04:52:31.848 if eqi is None:
2025-07-02 04:52:31.848 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.848 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.848 return
2025-07-02 04:52:31.848 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.848 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.849 else:
2025-07-02 04:52:31.849 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.849 eqi = None
2025-07-02 04:52:31.849
2025-07-02 04:52:31.849 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.849 # identical
2025-07-02 04:52:31.849
2025-07-02 04:52:31.849 # pump out diffs from before the synch point
2025-07-02 04:52:31.849 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.849
2025-07-02 04:52:31.849 # do intraline marking on the synch pair
2025-07-02 04:52:31.849 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.849 if eqi is None:
2025-07-02 04:52:31.849 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.849 atags = btags = ""
2025-07-02 04:52:31.849 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.849 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.849 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.849 if tag == 'replace':
2025-07-02 04:52:31.849 atags += '^' * la
2025-07-02 04:52:31.849 btags += '^' * lb
2025-07-02 04:52:31.850 elif tag == 'delete':
2025-07-02 04:52:31.850 atags += '-' * la
2025-07-02 04:52:31.850 elif tag == 'insert':
2025-07-02 04:52:31.850 btags += '+' * lb
2025-07-02 04:52:31.850 elif tag == 'equal':
2025-07-02 04:52:31.850 atags += ' ' * la
2025-07-02 04:52:31.850 btags += ' ' * lb
2025-07-02 04:52:31.850 else:
2025-07-02 04:52:31.850 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.850 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.850 else:
2025-07-02 04:52:31.850 # the synch pair is identical
2025-07-02 04:52:31.850 yield ' ' + aelt
2025-07-02 04:52:31.850
2025-07-02 04:52:31.850 # pump out diffs from after the synch point
2025-07-02 04:52:31.850 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.850
2025-07-02 04:52:31.850 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.850 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.850
2025-07-02 04:52:31.851 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.851 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.851 alo = 119, ahi = 1101
2025-07-02 04:52:31.851 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.851 blo = 119, bhi = 1101
2025-07-02 04:52:31.851
2025-07-02 04:52:31.851 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.851 g = []
2025-07-02 04:52:31.851 if alo < ahi:
2025-07-02 04:52:31.851 if blo < bhi:
2025-07-02 04:52:31.851 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.851 else:
2025-07-02 04:52:31.851 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.851 elif blo < bhi:
2025-07-02 04:52:31.851 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.851
2025-07-02 04:52:31.851 > yield from g
2025-07-02 04:52:31.851
2025-07-02 04:52:31.851 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.851 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.851
2025-07-02 04:52:31.852 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.852 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.852 alo = 119, ahi = 1101
2025-07-02 04:52:31.852 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.852 blo = 119, bhi = 1101
2025-07-02 04:52:31.852
2025-07-02 04:52:31.852 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.852 r"""
2025-07-02 04:52:31.852 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.852 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.852 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.852 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.852
2025-07-02 04:52:31.852 Example:
2025-07-02 04:52:31.852
2025-07-02 04:52:31.852 >>> d = Differ()
2025-07-02 04:52:31.852 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.852 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.852 >>> print(''.join(results), end="")
2025-07-02 04:52:31.853 - abcDefghiJkl
2025-07-02 04:52:31.853 + abcdefGhijkl
2025-07-02 04:52:31.853 """
2025-07-02 04:52:31.853
2025-07-02 04:52:31.853 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.853 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.853 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.853 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.853 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.853
2025-07-02 04:52:31.853 # search for the pair that matches best without being identical
2025-07-02 04:52:31.853 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.853 # on junk -- unless we have to)
2025-07-02 04:52:31.853 for j in range(blo, bhi):
2025-07-02 04:52:31.853 bj = b[j]
2025-07-02 04:52:31.853 cruncher.set_seq2(bj)
2025-07-02 04:52:31.853 for i in range(alo, ahi):
2025-07-02 04:52:31.853 ai = a[i]
2025-07-02 04:52:31.854 if ai == bj:
2025-07-02 04:52:31.854 if eqi is None:
2025-07-02 04:52:31.854 eqi, eqj = i, j
2025-07-02 04:52:31.854 continue
2025-07-02 04:52:31.854 cruncher.set_seq1(ai)
2025-07-02 04:52:31.854 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.854 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.854 # compares by a factor of 3.
2025-07-02 04:52:31.854 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.854 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.854 # of the computation is cached by cruncher
2025-07-02 04:52:31.854 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.854 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.854 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.854 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.854 if best_ratio < cutoff:
2025-07-02 04:52:31.854 # no non-identical "pretty close" pair
2025-07-02 04:52:31.854 if eqi is None:
2025-07-02 04:52:31.854 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.854 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.854 return
2025-07-02 04:52:31.855 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.855 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.855 else:
2025-07-02 04:52:31.855 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.855 eqi = None
2025-07-02 04:52:31.855
2025-07-02 04:52:31.855 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.855 # identical
2025-07-02 04:52:31.855
2025-07-02 04:52:31.855 # pump out diffs from before the synch point
2025-07-02 04:52:31.855 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.855
2025-07-02 04:52:31.855 # do intraline marking on the synch pair
2025-07-02 04:52:31.855 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.855 if eqi is None:
2025-07-02 04:52:31.855 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.855 atags = btags = ""
2025-07-02 04:52:31.855 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.855 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.855 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.856 if tag == 'replace':
2025-07-02 04:52:31.856 atags += '^' * la
2025-07-02 04:52:31.856 btags += '^' * lb
2025-07-02 04:52:31.856 elif tag == 'delete':
2025-07-02 04:52:31.856 atags += '-' * la
2025-07-02 04:52:31.856 elif tag == 'insert':
2025-07-02 04:52:31.856 btags += '+' * lb
2025-07-02 04:52:31.856 elif tag == 'equal':
2025-07-02 04:52:31.856 atags += ' ' * la
2025-07-02 04:52:31.856 btags += ' ' * lb
2025-07-02 04:52:31.856 else:
2025-07-02 04:52:31.856 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.856 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.856 else:
2025-07-02 04:52:31.856 # the synch pair is identical
2025-07-02 04:52:31.856 yield ' ' + aelt
2025-07-02 04:52:31.856
2025-07-02 04:52:31.856 # pump out diffs from after the synch point
2025-07-02 04:52:31.856 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.856
2025-07-02 04:52:31.856 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.857 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.857
2025-07-02 04:52:31.857 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.857 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.857 alo = 120, ahi = 1101
2025-07-02 04:52:31.857 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.857 blo = 120, bhi = 1101
2025-07-02 04:52:31.857
2025-07-02 04:52:31.857 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.857 g = []
2025-07-02 04:52:31.857 if alo < ahi:
2025-07-02 04:52:31.857 if blo < bhi:
2025-07-02 04:52:31.857 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.857 else:
2025-07-02 04:52:31.857 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.857 elif blo < bhi:
2025-07-02 04:52:31.857 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.857
2025-07-02 04:52:31.857 > yield from g
2025-07-02 04:52:31.857
2025-07-02 04:52:31.857 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.858 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.858
2025-07-02 04:52:31.858 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.858 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.858 alo = 120, ahi = 1101
2025-07-02 04:52:31.858 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.858 blo = 120, bhi = 1101
2025-07-02 04:52:31.858
2025-07-02 04:52:31.858 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.858 r"""
2025-07-02 04:52:31.858 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.858 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.858 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.858 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.858
2025-07-02 04:52:31.858 Example:
2025-07-02 04:52:31.858
2025-07-02 04:52:31.858 >>> d = Differ()
2025-07-02 04:52:31.858 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.859 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.859 >>> print(''.join(results), end="")
2025-07-02 04:52:31.859 - abcDefghiJkl
2025-07-02 04:52:31.859 + abcdefGhijkl
2025-07-02 04:52:31.859 """
2025-07-02 04:52:31.859
2025-07-02 04:52:31.859 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.859 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.859 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.859 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.859 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.859
2025-07-02 04:52:31.859 # search for the pair that matches best without being identical
2025-07-02 04:52:31.859 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.859 # on junk -- unless we have to)
2025-07-02 04:52:31.859 for j in range(blo, bhi):
2025-07-02 04:52:31.859 bj = b[j]
2025-07-02 04:52:31.859 cruncher.set_seq2(bj)
2025-07-02 04:52:31.859 for i in range(alo, ahi):
2025-07-02 04:52:31.860 ai = a[i]
2025-07-02 04:52:31.860 if ai == bj:
2025-07-02 04:52:31.860 if eqi is None:
2025-07-02 04:52:31.860 eqi, eqj = i, j
2025-07-02 04:52:31.860 continue
2025-07-02 04:52:31.860 cruncher.set_seq1(ai)
2025-07-02 04:52:31.860 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.860 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.860 # compares by a factor of 3.
2025-07-02 04:52:31.860 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.860 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.860 # of the computation is cached by cruncher
2025-07-02 04:52:31.860 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.860 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.860 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.860 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.860 if best_ratio < cutoff:
2025-07-02 04:52:31.860 # no non-identical "pretty close" pair
2025-07-02 04:52:31.860 if eqi is None:
2025-07-02 04:52:31.860 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.861 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.861 return
2025-07-02 04:52:31.861 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.861 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.861 else:
2025-07-02 04:52:31.861 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.861 eqi = None
2025-07-02 04:52:31.861
2025-07-02 04:52:31.861 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.861 # identical
2025-07-02 04:52:31.861
2025-07-02 04:52:31.861 # pump out diffs from before the synch point
2025-07-02 04:52:31.861 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.861
2025-07-02 04:52:31.861 # do intraline marking on the synch pair
2025-07-02 04:52:31.861 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.861 if eqi is None:
2025-07-02 04:52:31.861 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.861 atags = btags = ""
2025-07-02 04:52:31.861 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.862 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.862 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.862 if tag == 'replace':
2025-07-02 04:52:31.862 atags += '^' * la
2025-07-02 04:52:31.862 btags += '^' * lb
2025-07-02 04:52:31.862 elif tag == 'delete':
2025-07-02 04:52:31.862 atags += '-' * la
2025-07-02 04:52:31.862 elif tag == 'insert':
2025-07-02 04:52:31.862 btags += '+' * lb
2025-07-02 04:52:31.862 elif tag == 'equal':
2025-07-02 04:52:31.862 atags += ' ' * la
2025-07-02 04:52:31.862 btags += ' ' * lb
2025-07-02 04:52:31.862 else:
2025-07-02 04:52:31.862 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.862 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.862 else:
2025-07-02 04:52:31.862 # the synch pair is identical
2025-07-02 04:52:31.862 yield ' ' + aelt
2025-07-02 04:52:31.862
2025-07-02 04:52:31.862 # pump out diffs from after the synch point
2025-07-02 04:52:31.862 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.863
2025-07-02 04:52:31.863 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.863 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.863
2025-07-02 04:52:31.863 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.863 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.863 alo = 121, ahi = 1101
2025-07-02 04:52:31.863 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.863 blo = 121, bhi = 1101
2025-07-02 04:52:31.863
2025-07-02 04:52:31.863 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.863 g = []
2025-07-02 04:52:31.863 if alo < ahi:
2025-07-02 04:52:31.863 if blo < bhi:
2025-07-02 04:52:31.863 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.863 else:
2025-07-02 04:52:31.863 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.863 elif blo < bhi:
2025-07-02 04:52:31.863 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.863
2025-07-02 04:52:31.863 > yield from g
2025-07-02 04:52:31.864
2025-07-02 04:52:31.864 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.864 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.864
2025-07-02 04:52:31.864 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.864 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.864 alo = 121, ahi = 1101
2025-07-02 04:52:31.864 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.864 blo = 121, bhi = 1101
2025-07-02 04:52:31.864
2025-07-02 04:52:31.864 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.864 r"""
2025-07-02 04:52:31.864 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.864 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.864 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.864 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.864
2025-07-02 04:52:31.864 Example:
2025-07-02 04:52:31.864
2025-07-02 04:52:31.864 >>> d = Differ()
2025-07-02 04:52:31.865 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.865 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.865 >>> print(''.join(results), end="")
2025-07-02 04:52:31.865 - abcDefghiJkl
2025-07-02 04:52:31.865 + abcdefGhijkl
2025-07-02 04:52:31.865 """
2025-07-02 04:52:31.865
2025-07-02 04:52:31.865 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.865 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.865 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.865 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.865 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.865
2025-07-02 04:52:31.865 # search for the pair that matches best without being identical
2025-07-02 04:52:31.865 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.865 # on junk -- unless we have to)
2025-07-02 04:52:31.865 for j in range(blo, bhi):
2025-07-02 04:52:31.865 bj = b[j]
2025-07-02 04:52:31.865 cruncher.set_seq2(bj)
2025-07-02 04:52:31.866 for i in range(alo, ahi):
2025-07-02 04:52:31.866 ai = a[i]
2025-07-02 04:52:31.866 if ai == bj:
2025-07-02 04:52:31.866 if eqi is None:
2025-07-02 04:52:31.866 eqi, eqj = i, j
2025-07-02 04:52:31.866 continue
2025-07-02 04:52:31.866 cruncher.set_seq1(ai)
2025-07-02 04:52:31.866 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.866 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.866 # compares by a factor of 3.
2025-07-02 04:52:31.866 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.866 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.866 # of the computation is cached by cruncher
2025-07-02 04:52:31.866 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.866 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.866 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.866 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.866 if best_ratio < cutoff:
2025-07-02 04:52:31.866 # no non-identical "pretty close" pair
2025-07-02 04:52:31.867 if eqi is None:
2025-07-02 04:52:31.867 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.867 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.867 return
2025-07-02 04:52:31.867 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.867 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.867 else:
2025-07-02 04:52:31.867 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.867 eqi = None
2025-07-02 04:52:31.867
2025-07-02 04:52:31.867 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.867 # identical
2025-07-02 04:52:31.867
2025-07-02 04:52:31.867 # pump out diffs from before the synch point
2025-07-02 04:52:31.867 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.867
2025-07-02 04:52:31.867 # do intraline marking on the synch pair
2025-07-02 04:52:31.867 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.867 if eqi is None:
2025-07-02 04:52:31.867 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.867 atags = btags = ""
2025-07-02 04:52:31.868 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.868 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.868 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.868 if tag == 'replace':
2025-07-02 04:52:31.868 atags += '^' * la
2025-07-02 04:52:31.868 btags += '^' * lb
2025-07-02 04:52:31.868 elif tag == 'delete':
2025-07-02 04:52:31.868 atags += '-' * la
2025-07-02 04:52:31.868 elif tag == 'insert':
2025-07-02 04:52:31.868 btags += '+' * lb
2025-07-02 04:52:31.868 elif tag == 'equal':
2025-07-02 04:52:31.868 atags += ' ' * la
2025-07-02 04:52:31.868 btags += ' ' * lb
2025-07-02 04:52:31.868 else:
2025-07-02 04:52:31.868 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.868 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.868 else:
2025-07-02 04:52:31.868 # the synch pair is identical
2025-07-02 04:52:31.868 yield ' ' + aelt
2025-07-02 04:52:31.868
2025-07-02 04:52:31.868 # pump out diffs from after the synch point
2025-07-02 04:52:31.868 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.869
2025-07-02 04:52:31.869 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.869 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.869
2025-07-02 04:52:31.869 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.869 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.869 alo = 122, ahi = 1101
2025-07-02 04:52:31.869 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.869 blo = 122, bhi = 1101
2025-07-02 04:52:31.869
2025-07-02 04:52:31.869 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.869 g = []
2025-07-02 04:52:31.869 if alo < ahi:
2025-07-02 04:52:31.869 if blo < bhi:
2025-07-02 04:52:31.869 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.869 else:
2025-07-02 04:52:31.869 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.869 elif blo < bhi:
2025-07-02 04:52:31.870 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.870
2025-07-02 04:52:31.870 > yield from g
2025-07-02 04:52:31.870
2025-07-02 04:52:31.870 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.870 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.870
2025-07-02 04:52:31.870 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.870 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.870 alo = 122, ahi = 1101
2025-07-02 04:52:31.870 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.870 blo = 122, bhi = 1101
2025-07-02 04:52:31.870
2025-07-02 04:52:31.870 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.870 r"""
2025-07-02 04:52:31.870 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.870 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.870 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.870 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.870
2025-07-02 04:52:31.871 Example:
2025-07-02 04:52:31.871
2025-07-02 04:52:31.871 >>> d = Differ()
2025-07-02 04:52:31.871 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.871 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.871 >>> print(''.join(results), end="")
2025-07-02 04:52:31.871 - abcDefghiJkl
2025-07-02 04:52:31.871 + abcdefGhijkl
2025-07-02 04:52:31.871 """
2025-07-02 04:52:31.871
2025-07-02 04:52:31.871 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.871 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.871 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.871 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.871 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.871
2025-07-02 04:52:31.871 # search for the pair that matches best without being identical
2025-07-02 04:52:31.871 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.871 # on junk -- unless we have to)
2025-07-02 04:52:31.872 for j in range(blo, bhi):
2025-07-02 04:52:31.872 bj = b[j]
2025-07-02 04:52:31.872 cruncher.set_seq2(bj)
2025-07-02 04:52:31.872 for i in range(alo, ahi):
2025-07-02 04:52:31.872 ai = a[i]
2025-07-02 04:52:31.872 if ai == bj:
2025-07-02 04:52:31.872 if eqi is None:
2025-07-02 04:52:31.872 eqi, eqj = i, j
2025-07-02 04:52:31.872 continue
2025-07-02 04:52:31.872 cruncher.set_seq1(ai)
2025-07-02 04:52:31.872 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.872 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.872 # compares by a factor of 3.
2025-07-02 04:52:31.872 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.872 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.872 # of the computation is cached by cruncher
2025-07-02 04:52:31.872 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.872 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.872 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.872 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.873 if best_ratio < cutoff:
2025-07-02 04:52:31.873 # no non-identical "pretty close" pair
2025-07-02 04:52:31.873 if eqi is None:
2025-07-02 04:52:31.873 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.873 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.873 return
2025-07-02 04:52:31.873 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.873 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.873 else:
2025-07-02 04:52:31.873 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.873 eqi = None
2025-07-02 04:52:31.873
2025-07-02 04:52:31.873 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.873 # identical
2025-07-02 04:52:31.873
2025-07-02 04:52:31.873 # pump out diffs from before the synch point
2025-07-02 04:52:31.873 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.873
2025-07-02 04:52:31.873 # do intraline marking on the synch pair
2025-07-02 04:52:31.873 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.873 if eqi is None:
2025-07-02 04:52:31.874 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.874 atags = btags = ""
2025-07-02 04:52:31.874 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.874 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.874 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.874 if tag == 'replace':
2025-07-02 04:52:31.874 atags += '^' * la
2025-07-02 04:52:31.874 btags += '^' * lb
2025-07-02 04:52:31.874 elif tag == 'delete':
2025-07-02 04:52:31.874 atags += '-' * la
2025-07-02 04:52:31.874 elif tag == 'insert':
2025-07-02 04:52:31.874 btags += '+' * lb
2025-07-02 04:52:31.874 elif tag == 'equal':
2025-07-02 04:52:31.874 atags += ' ' * la
2025-07-02 04:52:31.874 btags += ' ' * lb
2025-07-02 04:52:31.874 else:
2025-07-02 04:52:31.874 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.874 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.874 else:
2025-07-02 04:52:31.874 # the synch pair is identical
2025-07-02 04:52:31.875 yield ' ' + aelt
2025-07-02 04:52:31.875
2025-07-02 04:52:31.875 # pump out diffs from after the synch point
2025-07-02 04:52:31.875 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.875
2025-07-02 04:52:31.875 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.875 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.875
2025-07-02 04:52:31.875 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.875 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.875 alo = 123, ahi = 1101
2025-07-02 04:52:31.875 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.875 blo = 123, bhi = 1101
2025-07-02 04:52:31.875
2025-07-02 04:52:31.875 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.875 g = []
2025-07-02 04:52:31.875 if alo < ahi:
2025-07-02 04:52:31.875 if blo < bhi:
2025-07-02 04:52:31.875 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.875 else:
2025-07-02 04:52:31.876 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.876 elif blo < bhi:
2025-07-02 04:52:31.876 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.876
2025-07-02 04:52:31.876 > yield from g
2025-07-02 04:52:31.876
2025-07-02 04:52:31.876 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.876 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.876
2025-07-02 04:52:31.876 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.876 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.876 alo = 123, ahi = 1101
2025-07-02 04:52:31.876 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.876 blo = 123, bhi = 1101
2025-07-02 04:52:31.876
2025-07-02 04:52:31.876 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.876 r"""
2025-07-02 04:52:31.876 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.876 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.876 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.876 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.877
2025-07-02 04:52:31.877 Example:
2025-07-02 04:52:31.877
2025-07-02 04:52:31.877 >>> d = Differ()
2025-07-02 04:52:31.877 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.877 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.877 >>> print(''.join(results), end="")
2025-07-02 04:52:31.877 - abcDefghiJkl
2025-07-02 04:52:31.877 + abcdefGhijkl
2025-07-02 04:52:31.877 """
2025-07-02 04:52:31.877
2025-07-02 04:52:31.877 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.877 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.877 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.877 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.877 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.877
2025-07-02 04:52:31.877 # search for the pair that matches best without being identical
2025-07-02 04:52:31.878 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.878 # on junk -- unless we have to)
2025-07-02 04:52:31.878 for j in range(blo, bhi):
2025-07-02 04:52:31.878 bj = b[j]
2025-07-02 04:52:31.878 cruncher.set_seq2(bj)
2025-07-02 04:52:31.878 for i in range(alo, ahi):
2025-07-02 04:52:31.878 ai = a[i]
2025-07-02 04:52:31.878 if ai == bj:
2025-07-02 04:52:31.878 if eqi is None:
2025-07-02 04:52:31.878 eqi, eqj = i, j
2025-07-02 04:52:31.878 continue
2025-07-02 04:52:31.878 cruncher.set_seq1(ai)
2025-07-02 04:52:31.878 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.878 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.878 # compares by a factor of 3.
2025-07-02 04:52:31.878 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.878 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.878 # of the computation is cached by cruncher
2025-07-02 04:52:31.878 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.878 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.879 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.879 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.879 if best_ratio < cutoff:
2025-07-02 04:52:31.879 # no non-identical "pretty close" pair
2025-07-02 04:52:31.879 if eqi is None:
2025-07-02 04:52:31.879 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.879 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.879 return
2025-07-02 04:52:31.879 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.879 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.879 else:
2025-07-02 04:52:31.879 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.879 eqi = None
2025-07-02 04:52:31.879
2025-07-02 04:52:31.879 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.879 # identical
2025-07-02 04:52:31.879
2025-07-02 04:52:31.879 # pump out diffs from before the synch point
2025-07-02 04:52:31.879 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.879
2025-07-02 04:52:31.879 # do intraline marking on the synch pair
2025-07-02 04:52:31.880 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.880 if eqi is None:
2025-07-02 04:52:31.880 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.880 atags = btags = ""
2025-07-02 04:52:31.880 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.880 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.880 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.880 if tag == 'replace':
2025-07-02 04:52:31.880 atags += '^' * la
2025-07-02 04:52:31.880 btags += '^' * lb
2025-07-02 04:52:31.880 elif tag == 'delete':
2025-07-02 04:52:31.880 atags += '-' * la
2025-07-02 04:52:31.880 elif tag == 'insert':
2025-07-02 04:52:31.880 btags += '+' * lb
2025-07-02 04:52:31.880 elif tag == 'equal':
2025-07-02 04:52:31.880 atags += ' ' * la
2025-07-02 04:52:31.880 btags += ' ' * lb
2025-07-02 04:52:31.880 else:
2025-07-02 04:52:31.880 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.880 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.881 else:
2025-07-02 04:52:31.881 # the synch pair is identical
2025-07-02 04:52:31.881 yield ' ' + aelt
2025-07-02 04:52:31.881
2025-07-02 04:52:31.881 # pump out diffs from after the synch point
2025-07-02 04:52:31.881 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.881
2025-07-02 04:52:31.881 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.881 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.881
2025-07-02 04:52:31.881 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.881 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.881 alo = 124, ahi = 1101
2025-07-02 04:52:31.881 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.881 blo = 124, bhi = 1101
2025-07-02 04:52:31.881
2025-07-02 04:52:31.881 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.881 g = []
2025-07-02 04:52:31.881 if alo < ahi:
2025-07-02 04:52:31.881 if blo < bhi:
2025-07-02 04:52:31.882 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.882 else:
2025-07-02 04:52:31.882 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.882 elif blo < bhi:
2025-07-02 04:52:31.882 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.882
2025-07-02 04:52:31.882 > yield from g
2025-07-02 04:52:31.882
2025-07-02 04:52:31.882 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.882 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.882
2025-07-02 04:52:31.882 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.882 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.882 alo = 124, ahi = 1101
2025-07-02 04:52:31.882 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.882 blo = 124, bhi = 1101
2025-07-02 04:52:31.882
2025-07-02 04:52:31.882 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.882 r"""
2025-07-02 04:52:31.882 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.883 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.883 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.883 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.883
2025-07-02 04:52:31.883 Example:
2025-07-02 04:52:31.883
2025-07-02 04:52:31.883 >>> d = Differ()
2025-07-02 04:52:31.883 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.883 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.883 >>> print(''.join(results), end="")
2025-07-02 04:52:31.883 - abcDefghiJkl
2025-07-02 04:52:31.883 + abcdefGhijkl
2025-07-02 04:52:31.883 """
2025-07-02 04:52:31.883
2025-07-02 04:52:31.883 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.883 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.883 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.883 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.884 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.884
2025-07-02 04:52:31.884 # search for the pair that matches best without being identical
2025-07-02 04:52:31.884 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.884 # on junk -- unless we have to)
2025-07-02 04:52:31.884 for j in range(blo, bhi):
2025-07-02 04:52:31.884 bj = b[j]
2025-07-02 04:52:31.884 cruncher.set_seq2(bj)
2025-07-02 04:52:31.884 for i in range(alo, ahi):
2025-07-02 04:52:31.884 ai = a[i]
2025-07-02 04:52:31.884 if ai == bj:
2025-07-02 04:52:31.884 if eqi is None:
2025-07-02 04:52:31.884 eqi, eqj = i, j
2025-07-02 04:52:31.884 continue
2025-07-02 04:52:31.884 cruncher.set_seq1(ai)
2025-07-02 04:52:31.884 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.884 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.884 # compares by a factor of 3.
2025-07-02 04:52:31.884 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.884 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.885 # of the computation is cached by cruncher
2025-07-02 04:52:31.885 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.885 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.885 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.885 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.885 if best_ratio < cutoff:
2025-07-02 04:52:31.885 # no non-identical "pretty close" pair
2025-07-02 04:52:31.885 if eqi is None:
2025-07-02 04:52:31.885 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.885 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.885 return
2025-07-02 04:52:31.885 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.885 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.885 else:
2025-07-02 04:52:31.885 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.885 eqi = None
2025-07-02 04:52:31.885
2025-07-02 04:52:31.885 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.885 # identical
2025-07-02 04:52:31.885
2025-07-02 04:52:31.886 # pump out diffs from before the synch point
2025-07-02 04:52:31.886 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.886
2025-07-02 04:52:31.886 # do intraline marking on the synch pair
2025-07-02 04:52:31.886 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.886 if eqi is None:
2025-07-02 04:52:31.886 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.886 atags = btags = ""
2025-07-02 04:52:31.886 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.886 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.886 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.886 if tag == 'replace':
2025-07-02 04:52:31.886 atags += '^' * la
2025-07-02 04:52:31.886 btags += '^' * lb
2025-07-02 04:52:31.886 elif tag == 'delete':
2025-07-02 04:52:31.886 atags += '-' * la
2025-07-02 04:52:31.886 elif tag == 'insert':
2025-07-02 04:52:31.886 btags += '+' * lb
2025-07-02 04:52:31.886 elif tag == 'equal':
2025-07-02 04:52:31.886 atags += ' ' * la
2025-07-02 04:52:31.887 btags += ' ' * lb
2025-07-02 04:52:31.887 else:
2025-07-02 04:52:31.887 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.887 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.887 else:
2025-07-02 04:52:31.887 # the synch pair is identical
2025-07-02 04:52:31.887 yield ' ' + aelt
2025-07-02 04:52:31.887
2025-07-02 04:52:31.887 # pump out diffs from after the synch point
2025-07-02 04:52:31.887 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.887
2025-07-02 04:52:31.887 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.887 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.887
2025-07-02 04:52:31.887 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.887 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.887 alo = 125, ahi = 1101
2025-07-02 04:52:31.887 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.887 blo = 125, bhi = 1101
2025-07-02 04:52:31.887
2025-07-02 04:52:31.887 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.887 g = []
2025-07-02 04:52:31.887 if alo < ahi:
2025-07-02 04:52:31.888 if blo < bhi:
2025-07-02 04:52:31.888 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.888 else:
2025-07-02 04:52:31.888 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.888 elif blo < bhi:
2025-07-02 04:52:31.888 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.888
2025-07-02 04:52:31.888 > yield from g
2025-07-02 04:52:31.888
2025-07-02 04:52:31.888 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.888 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.888
2025-07-02 04:52:31.888 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.888 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.888 alo = 125, ahi = 1101
2025-07-02 04:52:31.888 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.888 blo = 125, bhi = 1101
2025-07-02 04:52:31.888
2025-07-02 04:52:31.888 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.888 r"""
2025-07-02 04:52:31.888 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.889 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.889 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.889 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.889
2025-07-02 04:52:31.889 Example:
2025-07-02 04:52:31.889
2025-07-02 04:52:31.889 >>> d = Differ()
2025-07-02 04:52:31.889 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.889 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.889 >>> print(''.join(results), end="")
2025-07-02 04:52:31.889 - abcDefghiJkl
2025-07-02 04:52:31.889 + abcdefGhijkl
2025-07-02 04:52:31.889 """
2025-07-02 04:52:31.889
2025-07-02 04:52:31.889 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.889 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.889 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.889 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.889 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.890
2025-07-02 04:52:31.890 # search for the pair that matches best without being identical
2025-07-02 04:52:31.890 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.890 # on junk -- unless we have to)
2025-07-02 04:52:31.890 for j in range(blo, bhi):
2025-07-02 04:52:31.890 bj = b[j]
2025-07-02 04:52:31.890 cruncher.set_seq2(bj)
2025-07-02 04:52:31.890 for i in range(alo, ahi):
2025-07-02 04:52:31.890 ai = a[i]
2025-07-02 04:52:31.890 if ai == bj:
2025-07-02 04:52:31.890 if eqi is None:
2025-07-02 04:52:31.890 eqi, eqj = i, j
2025-07-02 04:52:31.890 continue
2025-07-02 04:52:31.890 cruncher.set_seq1(ai)
2025-07-02 04:52:31.890 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.890 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.890 # compares by a factor of 3.
2025-07-02 04:52:31.890 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.890 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.890 # of the computation is cached by cruncher
2025-07-02 04:52:31.890 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.890 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.891 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.891 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.891 if best_ratio < cutoff:
2025-07-02 04:52:31.891 # no non-identical "pretty close" pair
2025-07-02 04:52:31.891 if eqi is None:
2025-07-02 04:52:31.891 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.891 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.891 return
2025-07-02 04:52:31.891 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.891 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.891 else:
2025-07-02 04:52:31.891 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.891 eqi = None
2025-07-02 04:52:31.891
2025-07-02 04:52:31.891 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.891 # identical
2025-07-02 04:52:31.891
2025-07-02 04:52:31.891 # pump out diffs from before the synch point
2025-07-02 04:52:31.891 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.891
2025-07-02 04:52:31.891 # do intraline marking on the synch pair
2025-07-02 04:52:31.892 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.892 if eqi is None:
2025-07-02 04:52:31.892 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.892 atags = btags = ""
2025-07-02 04:52:31.892 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.892 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.892 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.892 if tag == 'replace':
2025-07-02 04:52:31.892 atags += '^' * la
2025-07-02 04:52:31.892 btags += '^' * lb
2025-07-02 04:52:31.892 elif tag == 'delete':
2025-07-02 04:52:31.892 atags += '-' * la
2025-07-02 04:52:31.892 elif tag == 'insert':
2025-07-02 04:52:31.892 btags += '+' * lb
2025-07-02 04:52:31.892 elif tag == 'equal':
2025-07-02 04:52:31.892 atags += ' ' * la
2025-07-02 04:52:31.892 btags += ' ' * lb
2025-07-02 04:52:31.892 else:
2025-07-02 04:52:31.892 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.892 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.892 else:
2025-07-02 04:52:31.892 # the synch pair is identical
2025-07-02 04:52:31.893 yield ' ' + aelt
2025-07-02 04:52:31.893
2025-07-02 04:52:31.893 # pump out diffs from after the synch point
2025-07-02 04:52:31.893 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.893
2025-07-02 04:52:31.893 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.893 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.893
2025-07-02 04:52:31.893 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.893 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.893 alo = 126, ahi = 1101
2025-07-02 04:52:31.893 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.893 blo = 126, bhi = 1101
2025-07-02 04:52:31.893
2025-07-02 04:52:31.893 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.893 g = []
2025-07-02 04:52:31.893 if alo < ahi:
2025-07-02 04:52:31.893 if blo < bhi:
2025-07-02 04:52:31.893 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.893 else:
2025-07-02 04:52:31.893 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.894 elif blo < bhi:
2025-07-02 04:52:31.894 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.894
2025-07-02 04:52:31.894 > yield from g
2025-07-02 04:52:31.894
2025-07-02 04:52:31.894 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.894 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.894
2025-07-02 04:52:31.894 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.894 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.894 alo = 126, ahi = 1101
2025-07-02 04:52:31.894 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.894 blo = 126, bhi = 1101
2025-07-02 04:52:31.894
2025-07-02 04:52:31.894 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.894 r"""
2025-07-02 04:52:31.894 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.894 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.894 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.895 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.895
2025-07-02 04:52:31.895 Example:
2025-07-02 04:52:31.895
2025-07-02 04:52:31.895 >>> d = Differ()
2025-07-02 04:52:31.895 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.895 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.895 >>> print(''.join(results), end="")
2025-07-02 04:52:31.895 - abcDefghiJkl
2025-07-02 04:52:31.895 + abcdefGhijkl
2025-07-02 04:52:31.895 """
2025-07-02 04:52:31.895
2025-07-02 04:52:31.895 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.895 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.895 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.895 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.895 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.895
2025-07-02 04:52:31.895 # search for the pair that matches best without being identical
2025-07-02 04:52:31.896 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.896 # on junk -- unless we have to)
2025-07-02 04:52:31.896 for j in range(blo, bhi):
2025-07-02 04:52:31.896 bj = b[j]
2025-07-02 04:52:31.896 cruncher.set_seq2(bj)
2025-07-02 04:52:31.896 for i in range(alo, ahi):
2025-07-02 04:52:31.896 ai = a[i]
2025-07-02 04:52:31.896 if ai == bj:
2025-07-02 04:52:31.896 if eqi is None:
2025-07-02 04:52:31.896 eqi, eqj = i, j
2025-07-02 04:52:31.896 continue
2025-07-02 04:52:31.896 cruncher.set_seq1(ai)
2025-07-02 04:52:31.896 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.896 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.896 # compares by a factor of 3.
2025-07-02 04:52:31.896 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.896 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.896 # of the computation is cached by cruncher
2025-07-02 04:52:31.896 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.896 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.896 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.897 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.897 if best_ratio < cutoff:
2025-07-02 04:52:31.897 # no non-identical "pretty close" pair
2025-07-02 04:52:31.897 if eqi is None:
2025-07-02 04:52:31.897 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.897 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.897 return
2025-07-02 04:52:31.897 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.897 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.897 else:
2025-07-02 04:52:31.897 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.897 eqi = None
2025-07-02 04:52:31.897
2025-07-02 04:52:31.897 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.897 # identical
2025-07-02 04:52:31.897
2025-07-02 04:52:31.897 # pump out diffs from before the synch point
2025-07-02 04:52:31.897 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.897
2025-07-02 04:52:31.898 # do intraline marking on the synch pair
2025-07-02 04:52:31.898 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.898 if eqi is None:
2025-07-02 04:52:31.898 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.898 atags = btags = ""
2025-07-02 04:52:31.898 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.898 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.898 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.898 if tag == 'replace':
2025-07-02 04:52:31.898 atags += '^' * la
2025-07-02 04:52:31.898 btags += '^' * lb
2025-07-02 04:52:31.898 elif tag == 'delete':
2025-07-02 04:52:31.898 atags += '-' * la
2025-07-02 04:52:31.898 elif tag == 'insert':
2025-07-02 04:52:31.898 btags += '+' * lb
2025-07-02 04:52:31.898 elif tag == 'equal':
2025-07-02 04:52:31.898 atags += ' ' * la
2025-07-02 04:52:31.898 btags += ' ' * lb
2025-07-02 04:52:31.898 else:
2025-07-02 04:52:31.898 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.898 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.899 else:
2025-07-02 04:52:31.899 # the synch pair is identical
2025-07-02 04:52:31.899 yield ' ' + aelt
2025-07-02 04:52:31.899
2025-07-02 04:52:31.899 # pump out diffs from after the synch point
2025-07-02 04:52:31.899 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.899
2025-07-02 04:52:31.899 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.899 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.899
2025-07-02 04:52:31.899 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.899 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.899 alo = 127, ahi = 1101
2025-07-02 04:52:31.899 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.899 blo = 127, bhi = 1101
2025-07-02 04:52:31.899
2025-07-02 04:52:31.899 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.899 g = []
2025-07-02 04:52:31.899 if alo < ahi:
2025-07-02 04:52:31.899 if blo < bhi:
2025-07-02 04:52:31.899 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.900 else:
2025-07-02 04:52:31.900 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.900 elif blo < bhi:
2025-07-02 04:52:31.900 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.900
2025-07-02 04:52:31.900 > yield from g
2025-07-02 04:52:31.900
2025-07-02 04:52:31.900 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.900 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.900
2025-07-02 04:52:31.900 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.900 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.900 alo = 127, ahi = 1101
2025-07-02 04:52:31.900 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.900 blo = 127, bhi = 1101
2025-07-02 04:52:31.900
2025-07-02 04:52:31.900 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.900 r"""
2025-07-02 04:52:31.900 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.900 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.900 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.900 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.901
2025-07-02 04:52:31.901 Example:
2025-07-02 04:52:31.901
2025-07-02 04:52:31.901 >>> d = Differ()
2025-07-02 04:52:31.901 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.901 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.901 >>> print(''.join(results), end="")
2025-07-02 04:52:31.901 - abcDefghiJkl
2025-07-02 04:52:31.901 + abcdefGhijkl
2025-07-02 04:52:31.901 """
2025-07-02 04:52:31.901
2025-07-02 04:52:31.901 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.901 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.901 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.901 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.901 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.901
2025-07-02 04:52:31.901 # search for the pair that matches best without being identical
2025-07-02 04:52:31.901 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.902 # on junk -- unless we have to)
2025-07-02 04:52:31.902 for j in range(blo, bhi):
2025-07-02 04:52:31.902 bj = b[j]
2025-07-02 04:52:31.902 cruncher.set_seq2(bj)
2025-07-02 04:52:31.902 for i in range(alo, ahi):
2025-07-02 04:52:31.902 ai = a[i]
2025-07-02 04:52:31.902 if ai == bj:
2025-07-02 04:52:31.902 if eqi is None:
2025-07-02 04:52:31.902 eqi, eqj = i, j
2025-07-02 04:52:31.902 continue
2025-07-02 04:52:31.902 cruncher.set_seq1(ai)
2025-07-02 04:52:31.902 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.902 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.902 # compares by a factor of 3.
2025-07-02 04:52:31.902 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.902 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.902 # of the computation is cached by cruncher
2025-07-02 04:52:31.902 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.902 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.902 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.903 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.903 if best_ratio < cutoff:
2025-07-02 04:52:31.903 # no non-identical "pretty close" pair
2025-07-02 04:52:31.903 if eqi is None:
2025-07-02 04:52:31.903 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.903 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.903 return
2025-07-02 04:52:31.903 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.903 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.903 else:
2025-07-02 04:52:31.903 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.903 eqi = None
2025-07-02 04:52:31.903
2025-07-02 04:52:31.903 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.903 # identical
2025-07-02 04:52:31.903
2025-07-02 04:52:31.903 # pump out diffs from before the synch point
2025-07-02 04:52:31.903 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.903
2025-07-02 04:52:31.903 # do intraline marking on the synch pair
2025-07-02 04:52:31.904 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.904 if eqi is None:
2025-07-02 04:52:31.904 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.904 atags = btags = ""
2025-07-02 04:52:31.904 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.904 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.904 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.904 if tag == 'replace':
2025-07-02 04:52:31.904 atags += '^' * la
2025-07-02 04:52:31.904 btags += '^' * lb
2025-07-02 04:52:31.904 elif tag == 'delete':
2025-07-02 04:52:31.904 atags += '-' * la
2025-07-02 04:52:31.904 elif tag == 'insert':
2025-07-02 04:52:31.904 btags += '+' * lb
2025-07-02 04:52:31.904 elif tag == 'equal':
2025-07-02 04:52:31.904 atags += ' ' * la
2025-07-02 04:52:31.904 btags += ' ' * lb
2025-07-02 04:52:31.904 else:
2025-07-02 04:52:31.904 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.904 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.904 else:
2025-07-02 04:52:31.905 # the synch pair is identical
2025-07-02 04:52:31.905 yield ' ' + aelt
2025-07-02 04:52:31.905
2025-07-02 04:52:31.905 # pump out diffs from after the synch point
2025-07-02 04:52:31.905 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.905
2025-07-02 04:52:31.905 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.905 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.905
2025-07-02 04:52:31.905 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.905 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.905 alo = 128, ahi = 1101
2025-07-02 04:52:31.905 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.905 blo = 128, bhi = 1101
2025-07-02 04:52:31.905
2025-07-02 04:52:31.905 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.905 g = []
2025-07-02 04:52:31.905 if alo < ahi:
2025-07-02 04:52:31.905 if blo < bhi:
2025-07-02 04:52:31.905 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.905 else:
2025-07-02 04:52:31.906 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.906 elif blo < bhi:
2025-07-02 04:52:31.906 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.906
2025-07-02 04:52:31.906 > yield from g
2025-07-02 04:52:31.906
2025-07-02 04:52:31.906 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.906 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.906
2025-07-02 04:52:31.906 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.906 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.906 alo = 128, ahi = 1101
2025-07-02 04:52:31.906 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.906 blo = 128, bhi = 1101
2025-07-02 04:52:31.906
2025-07-02 04:52:31.906 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.906 r"""
2025-07-02 04:52:31.906 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.906 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.906 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.906 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.907
2025-07-02 04:52:31.907 Example:
2025-07-02 04:52:31.907
2025-07-02 04:52:31.907 >>> d = Differ()
2025-07-02 04:52:31.907 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.907 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.907 >>> print(''.join(results), end="")
2025-07-02 04:52:31.907 - abcDefghiJkl
2025-07-02 04:52:31.907 + abcdefGhijkl
2025-07-02 04:52:31.907 """
2025-07-02 04:52:31.907
2025-07-02 04:52:31.907 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.907 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.907 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.907 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.907 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.907
2025-07-02 04:52:31.907 # search for the pair that matches best without being identical
2025-07-02 04:52:31.907 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.907 # on junk -- unless we have to)
2025-07-02 04:52:31.908 for j in range(blo, bhi):
2025-07-02 04:52:31.908 bj = b[j]
2025-07-02 04:52:31.908 cruncher.set_seq2(bj)
2025-07-02 04:52:31.908 for i in range(alo, ahi):
2025-07-02 04:52:31.908 ai = a[i]
2025-07-02 04:52:31.908 if ai == bj:
2025-07-02 04:52:31.908 if eqi is None:
2025-07-02 04:52:31.908 eqi, eqj = i, j
2025-07-02 04:52:31.908 continue
2025-07-02 04:52:31.908 cruncher.set_seq1(ai)
2025-07-02 04:52:31.908 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.908 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.908 # compares by a factor of 3.
2025-07-02 04:52:31.908 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.908 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.908 # of the computation is cached by cruncher
2025-07-02 04:52:31.908 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.908 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.908 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.908 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.908 if best_ratio < cutoff:
2025-07-02 04:52:31.909 # no non-identical "pretty close" pair
2025-07-02 04:52:31.909 if eqi is None:
2025-07-02 04:52:31.909 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.909 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.909 return
2025-07-02 04:52:31.909 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.909 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.909 else:
2025-07-02 04:52:31.909 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.909 eqi = None
2025-07-02 04:52:31.909
2025-07-02 04:52:31.909 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.909 # identical
2025-07-02 04:52:31.909
2025-07-02 04:52:31.909 # pump out diffs from before the synch point
2025-07-02 04:52:31.909 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.909
2025-07-02 04:52:31.909 # do intraline marking on the synch pair
2025-07-02 04:52:31.909 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.909 if eqi is None:
2025-07-02 04:52:31.909 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.909 atags = btags = ""
2025-07-02 04:52:31.910 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.910 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.910 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.910 if tag == 'replace':
2025-07-02 04:52:31.910 atags += '^' * la
2025-07-02 04:52:31.910 btags += '^' * lb
2025-07-02 04:52:31.910 elif tag == 'delete':
2025-07-02 04:52:31.910 atags += '-' * la
2025-07-02 04:52:31.910 elif tag == 'insert':
2025-07-02 04:52:31.910 btags += '+' * lb
2025-07-02 04:52:31.910 elif tag == 'equal':
2025-07-02 04:52:31.910 atags += ' ' * la
2025-07-02 04:52:31.910 btags += ' ' * lb
2025-07-02 04:52:31.910 else:
2025-07-02 04:52:31.910 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.910 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.910 else:
2025-07-02 04:52:31.910 # the synch pair is identical
2025-07-02 04:52:31.910 yield ' ' + aelt
2025-07-02 04:52:31.910
2025-07-02 04:52:31.910 # pump out diffs from after the synch point
2025-07-02 04:52:31.911 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.911
2025-07-02 04:52:31.911 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.911 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.911
2025-07-02 04:52:31.911 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.911 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.911 alo = 129, ahi = 1101
2025-07-02 04:52:31.911 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.911 blo = 129, bhi = 1101
2025-07-02 04:52:31.911
2025-07-02 04:52:31.911 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.911 g = []
2025-07-02 04:52:31.911 if alo < ahi:
2025-07-02 04:52:31.911 if blo < bhi:
2025-07-02 04:52:31.911 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.911 else:
2025-07-02 04:52:31.911 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.911 elif blo < bhi:
2025-07-02 04:52:31.911 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.912
2025-07-02 04:52:31.912 > yield from g
2025-07-02 04:52:31.912
2025-07-02 04:52:31.912 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.912 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.912
2025-07-02 04:52:31.912 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.912 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.912 alo = 129, ahi = 1101
2025-07-02 04:52:31.912 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.912 blo = 129, bhi = 1101
2025-07-02 04:52:31.912
2025-07-02 04:52:31.912 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.912 r"""
2025-07-02 04:52:31.912 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.912 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.912 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.912 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.912
2025-07-02 04:52:31.912 Example:
2025-07-02 04:52:31.913
2025-07-02 04:52:31.913 >>> d = Differ()
2025-07-02 04:52:31.913 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.913 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.913 >>> print(''.join(results), end="")
2025-07-02 04:52:31.913 - abcDefghiJkl
2025-07-02 04:52:31.913 + abcdefGhijkl
2025-07-02 04:52:31.913 """
2025-07-02 04:52:31.913
2025-07-02 04:52:31.913 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.913 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.913 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.913 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.913 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.913
2025-07-02 04:52:31.913 # search for the pair that matches best without being identical
2025-07-02 04:52:31.913 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.914 # on junk -- unless we have to)
2025-07-02 04:52:31.914 for j in range(blo, bhi):
2025-07-02 04:52:31.914 bj = b[j]
2025-07-02 04:52:31.914 cruncher.set_seq2(bj)
2025-07-02 04:52:31.914 for i in range(alo, ahi):
2025-07-02 04:52:31.914 ai = a[i]
2025-07-02 04:52:31.914 if ai == bj:
2025-07-02 04:52:31.914 if eqi is None:
2025-07-02 04:52:31.914 eqi, eqj = i, j
2025-07-02 04:52:31.914 continue
2025-07-02 04:52:31.914 cruncher.set_seq1(ai)
2025-07-02 04:52:31.914 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.914 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.914 # compares by a factor of 3.
2025-07-02 04:52:31.914 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.914 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.914 # of the computation is cached by cruncher
2025-07-02 04:52:31.914 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.914 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.914 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.914 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.915 if best_ratio < cutoff:
2025-07-02 04:52:31.915 # no non-identical "pretty close" pair
2025-07-02 04:52:31.915 if eqi is None:
2025-07-02 04:52:31.915 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.915 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.915 return
2025-07-02 04:52:31.915 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.915 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.915 else:
2025-07-02 04:52:31.915 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.915 eqi = None
2025-07-02 04:52:31.915
2025-07-02 04:52:31.915 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.915 # identical
2025-07-02 04:52:31.915
2025-07-02 04:52:31.915 # pump out diffs from before the synch point
2025-07-02 04:52:31.915 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.915
2025-07-02 04:52:31.915 # do intraline marking on the synch pair
2025-07-02 04:52:31.915 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.915 if eqi is None:
2025-07-02 04:52:31.916 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.916 atags = btags = ""
2025-07-02 04:52:31.916 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.916 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.916 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.916 if tag == 'replace':
2025-07-02 04:52:31.916 atags += '^' * la
2025-07-02 04:52:31.916 btags += '^' * lb
2025-07-02 04:52:31.916 elif tag == 'delete':
2025-07-02 04:52:31.916 atags += '-' * la
2025-07-02 04:52:31.916 elif tag == 'insert':
2025-07-02 04:52:31.916 btags += '+' * lb
2025-07-02 04:52:31.916 elif tag == 'equal':
2025-07-02 04:52:31.916 atags += ' ' * la
2025-07-02 04:52:31.916 btags += ' ' * lb
2025-07-02 04:52:31.916 else:
2025-07-02 04:52:31.916 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.916 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.916 else:
2025-07-02 04:52:31.916 # the synch pair is identical
2025-07-02 04:52:31.916 yield ' ' + aelt
2025-07-02 04:52:31.916
2025-07-02 04:52:31.917 # pump out diffs from after the synch point
2025-07-02 04:52:31.917 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.917
2025-07-02 04:52:31.917 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.917 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.917
2025-07-02 04:52:31.917 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.917 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.917 alo = 130, ahi = 1101
2025-07-02 04:52:31.917 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.917 blo = 130, bhi = 1101
2025-07-02 04:52:31.917
2025-07-02 04:52:31.917 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.917 g = []
2025-07-02 04:52:31.917 if alo < ahi:
2025-07-02 04:52:31.917 if blo < bhi:
2025-07-02 04:52:31.917 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.917 else:
2025-07-02 04:52:31.917 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.917 elif blo < bhi:
2025-07-02 04:52:31.917 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.918
2025-07-02 04:52:31.918 > yield from g
2025-07-02 04:52:31.918
2025-07-02 04:52:31.918 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.918 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.918
2025-07-02 04:52:31.918 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.918 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.918 alo = 130, ahi = 1101
2025-07-02 04:52:31.918 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.918 blo = 130, bhi = 1101
2025-07-02 04:52:31.918
2025-07-02 04:52:31.918 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.918 r"""
2025-07-02 04:52:31.918 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.918 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.918 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.918 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.918
2025-07-02 04:52:31.918 Example:
2025-07-02 04:52:31.918
2025-07-02 04:52:31.919 >>> d = Differ()
2025-07-02 04:52:31.919 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.919 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.919 >>> print(''.join(results), end="")
2025-07-02 04:52:31.919 - abcDefghiJkl
2025-07-02 04:52:31.919 + abcdefGhijkl
2025-07-02 04:52:31.919 """
2025-07-02 04:52:31.919
2025-07-02 04:52:31.919 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.919 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.919 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.919 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.919 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.919
2025-07-02 04:52:31.919 # search for the pair that matches best without being identical
2025-07-02 04:52:31.919 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.919 # on junk -- unless we have to)
2025-07-02 04:52:31.920 for j in range(blo, bhi):
2025-07-02 04:52:31.920 bj = b[j]
2025-07-02 04:52:31.920 cruncher.set_seq2(bj)
2025-07-02 04:52:31.920 for i in range(alo, ahi):
2025-07-02 04:52:31.920 ai = a[i]
2025-07-02 04:52:31.920 if ai == bj:
2025-07-02 04:52:31.920 if eqi is None:
2025-07-02 04:52:31.920 eqi, eqj = i, j
2025-07-02 04:52:31.920 continue
2025-07-02 04:52:31.920 cruncher.set_seq1(ai)
2025-07-02 04:52:31.920 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.920 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.920 # compares by a factor of 3.
2025-07-02 04:52:31.920 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.920 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.920 # of the computation is cached by cruncher
2025-07-02 04:52:31.920 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.920 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.921 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.921 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.921 if best_ratio < cutoff:
2025-07-02 04:52:31.921 # no non-identical "pretty close" pair
2025-07-02 04:52:31.921 if eqi is None:
2025-07-02 04:52:31.921 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.921 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.921 return
2025-07-02 04:52:31.921 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.921 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.921 else:
2025-07-02 04:52:31.921 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.921 eqi = None
2025-07-02 04:52:31.921
2025-07-02 04:52:31.921 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.921 # identical
2025-07-02 04:52:31.921
2025-07-02 04:52:31.921 # pump out diffs from before the synch point
2025-07-02 04:52:31.921 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.921
2025-07-02 04:52:31.921 # do intraline marking on the synch pair
2025-07-02 04:52:31.922 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.922 if eqi is None:
2025-07-02 04:52:31.922 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.922 atags = btags = ""
2025-07-02 04:52:31.922 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.922 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.922 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.922 if tag == 'replace':
2025-07-02 04:52:31.922 atags += '^' * la
2025-07-02 04:52:31.922 btags += '^' * lb
2025-07-02 04:52:31.922 elif tag == 'delete':
2025-07-02 04:52:31.922 atags += '-' * la
2025-07-02 04:52:31.922 elif tag == 'insert':
2025-07-02 04:52:31.922 btags += '+' * lb
2025-07-02 04:52:31.922 elif tag == 'equal':
2025-07-02 04:52:31.922 atags += ' ' * la
2025-07-02 04:52:31.922 btags += ' ' * lb
2025-07-02 04:52:31.922 else:
2025-07-02 04:52:31.922 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.922 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.922 else:
2025-07-02 04:52:31.923 # the synch pair is identical
2025-07-02 04:52:31.923 yield ' ' + aelt
2025-07-02 04:52:31.923
2025-07-02 04:52:31.923 # pump out diffs from after the synch point
2025-07-02 04:52:31.923 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.923
2025-07-02 04:52:31.923 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.923 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.923
2025-07-02 04:52:31.923 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.923 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.923 alo = 131, ahi = 1101
2025-07-02 04:52:31.923 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.923 blo = 131, bhi = 1101
2025-07-02 04:52:31.923
2025-07-02 04:52:31.923 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.923 g = []
2025-07-02 04:52:31.923 if alo < ahi:
2025-07-02 04:52:31.923 if blo < bhi:
2025-07-02 04:52:31.923 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.923 else:
2025-07-02 04:52:31.924 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.924 elif blo < bhi:
2025-07-02 04:52:31.924 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.924
2025-07-02 04:52:31.924 > yield from g
2025-07-02 04:52:31.924
2025-07-02 04:52:31.924 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.924 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.924
2025-07-02 04:52:31.924 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.924 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.924 alo = 131, ahi = 1101
2025-07-02 04:52:31.924 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.924 blo = 131, bhi = 1101
2025-07-02 04:52:31.924
2025-07-02 04:52:31.924 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.924 r"""
2025-07-02 04:52:31.924 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.924 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.924 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.924 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.924
2025-07-02 04:52:31.925 Example:
2025-07-02 04:52:31.925
2025-07-02 04:52:31.925 >>> d = Differ()
2025-07-02 04:52:31.925 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.925 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.925 >>> print(''.join(results), end="")
2025-07-02 04:52:31.925 - abcDefghiJkl
2025-07-02 04:52:31.925 + abcdefGhijkl
2025-07-02 04:52:31.925 """
2025-07-02 04:52:31.925
2025-07-02 04:52:31.925 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.925 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.925 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.925 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.925 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.925
2025-07-02 04:52:31.925 # search for the pair that matches best without being identical
2025-07-02 04:52:31.925 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.925 # on junk -- unless we have to)
2025-07-02 04:52:31.926 for j in range(blo, bhi):
2025-07-02 04:52:31.926 bj = b[j]
2025-07-02 04:52:31.926 cruncher.set_seq2(bj)
2025-07-02 04:52:31.926 for i in range(alo, ahi):
2025-07-02 04:52:31.926 ai = a[i]
2025-07-02 04:52:31.926 if ai == bj:
2025-07-02 04:52:31.926 if eqi is None:
2025-07-02 04:52:31.926 eqi, eqj = i, j
2025-07-02 04:52:31.926 continue
2025-07-02 04:52:31.926 cruncher.set_seq1(ai)
2025-07-02 04:52:31.926 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.926 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.926 # compares by a factor of 3.
2025-07-02 04:52:31.926 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.926 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.926 # of the computation is cached by cruncher
2025-07-02 04:52:31.926 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.926 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.926 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.926 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.926 if best_ratio < cutoff:
2025-07-02 04:52:31.926 # no non-identical "pretty close" pair
2025-07-02 04:52:31.927 if eqi is None:
2025-07-02 04:52:31.927 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.927 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.927 return
2025-07-02 04:52:31.927 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.927 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.927 else:
2025-07-02 04:52:31.927 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.927 eqi = None
2025-07-02 04:52:31.927
2025-07-02 04:52:31.927 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.927 # identical
2025-07-02 04:52:31.927
2025-07-02 04:52:31.927 # pump out diffs from before the synch point
2025-07-02 04:52:31.927 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.927
2025-07-02 04:52:31.927 # do intraline marking on the synch pair
2025-07-02 04:52:31.927 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.927 if eqi is None:
2025-07-02 04:52:31.927 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.928 atags = btags = ""
2025-07-02 04:52:31.928 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.928 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.928 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.928 if tag == 'replace':
2025-07-02 04:52:31.928 atags += '^' * la
2025-07-02 04:52:31.928 btags += '^' * lb
2025-07-02 04:52:31.928 elif tag == 'delete':
2025-07-02 04:52:31.928 atags += '-' * la
2025-07-02 04:52:31.928 elif tag == 'insert':
2025-07-02 04:52:31.928 btags += '+' * lb
2025-07-02 04:52:31.928 elif tag == 'equal':
2025-07-02 04:52:31.928 atags += ' ' * la
2025-07-02 04:52:31.928 btags += ' ' * lb
2025-07-02 04:52:31.928 else:
2025-07-02 04:52:31.928 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.928 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.928 else:
2025-07-02 04:52:31.928 # the synch pair is identical
2025-07-02 04:52:31.929 yield ' ' + aelt
2025-07-02 04:52:31.929
2025-07-02 04:52:31.929 # pump out diffs from after the synch point
2025-07-02 04:52:31.929 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.929
2025-07-02 04:52:31.929 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.929 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.929
2025-07-02 04:52:31.929 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.929 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.929 alo = 132, ahi = 1101
2025-07-02 04:52:31.929 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.929 blo = 132, bhi = 1101
2025-07-02 04:52:31.929
2025-07-02 04:52:31.929 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.929 g = []
2025-07-02 04:52:31.929 if alo < ahi:
2025-07-02 04:52:31.929 if blo < bhi:
2025-07-02 04:52:31.929 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.929 else:
2025-07-02 04:52:31.929 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.930 elif blo < bhi:
2025-07-02 04:52:31.930 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.930
2025-07-02 04:52:31.930 > yield from g
2025-07-02 04:52:31.930
2025-07-02 04:52:31.930 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.930 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.930
2025-07-02 04:52:31.930 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.930 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.930 alo = 132, ahi = 1101
2025-07-02 04:52:31.930 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.930 blo = 132, bhi = 1101
2025-07-02 04:52:31.930
2025-07-02 04:52:31.930 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.930 r"""
2025-07-02 04:52:31.930 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.930 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.930 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.930 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.930
2025-07-02 04:52:31.931 Example:
2025-07-02 04:52:31.931
2025-07-02 04:52:31.931 >>> d = Differ()
2025-07-02 04:52:31.931 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.931 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.931 >>> print(''.join(results), end="")
2025-07-02 04:52:31.931 - abcDefghiJkl
2025-07-02 04:52:31.931 + abcdefGhijkl
2025-07-02 04:52:31.931 """
2025-07-02 04:52:31.931
2025-07-02 04:52:31.931 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.931 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.931 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.931 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.931 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.931
2025-07-02 04:52:31.931 # search for the pair that matches best without being identical
2025-07-02 04:52:31.931 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.931 # on junk -- unless we have to)
2025-07-02 04:52:31.931 for j in range(blo, bhi):
2025-07-02 04:52:31.932 bj = b[j]
2025-07-02 04:52:31.932 cruncher.set_seq2(bj)
2025-07-02 04:52:31.932 for i in range(alo, ahi):
2025-07-02 04:52:31.932 ai = a[i]
2025-07-02 04:52:31.932 if ai == bj:
2025-07-02 04:52:31.932 if eqi is None:
2025-07-02 04:52:31.932 eqi, eqj = i, j
2025-07-02 04:52:31.932 continue
2025-07-02 04:52:31.932 cruncher.set_seq1(ai)
2025-07-02 04:52:31.932 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.932 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.932 # compares by a factor of 3.
2025-07-02 04:52:31.932 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.932 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.932 # of the computation is cached by cruncher
2025-07-02 04:52:31.932 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.932 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.932 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.932 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.932 if best_ratio < cutoff:
2025-07-02 04:52:31.932 # no non-identical "pretty close" pair
2025-07-02 04:52:31.932 if eqi is None:
2025-07-02 04:52:31.933 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.933 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.933 return
2025-07-02 04:52:31.933 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.933 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.933 else:
2025-07-02 04:52:31.933 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.933 eqi = None
2025-07-02 04:52:31.933
2025-07-02 04:52:31.933 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.933 # identical
2025-07-02 04:52:31.933
2025-07-02 04:52:31.933 # pump out diffs from before the synch point
2025-07-02 04:52:31.933 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.933
2025-07-02 04:52:31.933 # do intraline marking on the synch pair
2025-07-02 04:52:31.933 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.933 if eqi is None:
2025-07-02 04:52:31.933 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.933 atags = btags = ""
2025-07-02 04:52:31.933 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.934 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.934 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.934 if tag == 'replace':
2025-07-02 04:52:31.934 atags += '^' * la
2025-07-02 04:52:31.934 btags += '^' * lb
2025-07-02 04:52:31.934 elif tag == 'delete':
2025-07-02 04:52:31.934 atags += '-' * la
2025-07-02 04:52:31.934 elif tag == 'insert':
2025-07-02 04:52:31.934 btags += '+' * lb
2025-07-02 04:52:31.934 elif tag == 'equal':
2025-07-02 04:52:31.934 atags += ' ' * la
2025-07-02 04:52:31.934 btags += ' ' * lb
2025-07-02 04:52:31.934 else:
2025-07-02 04:52:31.934 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.934 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.934 else:
2025-07-02 04:52:31.934 # the synch pair is identical
2025-07-02 04:52:31.934 yield ' ' + aelt
2025-07-02 04:52:31.934
2025-07-02 04:52:31.934 # pump out diffs from after the synch point
2025-07-02 04:52:31.934 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.935
2025-07-02 04:52:31.935 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.935 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.935
2025-07-02 04:52:31.935 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.935 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.935 alo = 133, ahi = 1101
2025-07-02 04:52:31.935 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.935 blo = 133, bhi = 1101
2025-07-02 04:52:31.935
2025-07-02 04:52:31.935 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.935 g = []
2025-07-02 04:52:31.935 if alo < ahi:
2025-07-02 04:52:31.935 if blo < bhi:
2025-07-02 04:52:31.935 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.935 else:
2025-07-02 04:52:31.935 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.935 elif blo < bhi:
2025-07-02 04:52:31.935 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.936
2025-07-02 04:52:31.936 > yield from g
2025-07-02 04:52:31.936
2025-07-02 04:52:31.936 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.936 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.936
2025-07-02 04:52:31.936 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.936 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.936 alo = 133, ahi = 1101
2025-07-02 04:52:31.936 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.936 blo = 133, bhi = 1101
2025-07-02 04:52:31.936
2025-07-02 04:52:31.936 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.936 r"""
2025-07-02 04:52:31.936 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.936 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.936 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.936 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.936
2025-07-02 04:52:31.936 Example:
2025-07-02 04:52:31.937
2025-07-02 04:52:31.937 >>> d = Differ()
2025-07-02 04:52:31.937 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.937 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.937 >>> print(''.join(results), end="")
2025-07-02 04:52:31.937 - abcDefghiJkl
2025-07-02 04:52:31.937 + abcdefGhijkl
2025-07-02 04:52:31.937 """
2025-07-02 04:52:31.937
2025-07-02 04:52:31.937 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.937 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.937 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.937 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.937 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.937
2025-07-02 04:52:31.937 # search for the pair that matches best without being identical
2025-07-02 04:52:31.937 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.937 # on junk -- unless we have to)
2025-07-02 04:52:31.937 for j in range(blo, bhi):
2025-07-02 04:52:31.938 bj = b[j]
2025-07-02 04:52:31.938 cruncher.set_seq2(bj)
2025-07-02 04:52:31.938 for i in range(alo, ahi):
2025-07-02 04:52:31.938 ai = a[i]
2025-07-02 04:52:31.938 if ai == bj:
2025-07-02 04:52:31.938 if eqi is None:
2025-07-02 04:52:31.938 eqi, eqj = i, j
2025-07-02 04:52:31.938 continue
2025-07-02 04:52:31.938 cruncher.set_seq1(ai)
2025-07-02 04:52:31.938 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.938 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.938 # compares by a factor of 3.
2025-07-02 04:52:31.938 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.938 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.938 # of the computation is cached by cruncher
2025-07-02 04:52:31.938 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.938 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.938 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.938 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.938 if best_ratio < cutoff:
2025-07-02 04:52:31.938 # no non-identical "pretty close" pair
2025-07-02 04:52:31.939 if eqi is None:
2025-07-02 04:52:31.939 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.939 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.939 return
2025-07-02 04:52:31.939 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.939 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.939 else:
2025-07-02 04:52:31.939 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.939 eqi = None
2025-07-02 04:52:31.939
2025-07-02 04:52:31.939 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.939 # identical
2025-07-02 04:52:31.939
2025-07-02 04:52:31.939 # pump out diffs from before the synch point
2025-07-02 04:52:31.939 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.939
2025-07-02 04:52:31.939 # do intraline marking on the synch pair
2025-07-02 04:52:31.939 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.939 if eqi is None:
2025-07-02 04:52:31.939 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.939 atags = btags = ""
2025-07-02 04:52:31.939 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.940 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.940 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.940 if tag == 'replace':
2025-07-02 04:52:31.940 atags += '^' * la
2025-07-02 04:52:31.940 btags += '^' * lb
2025-07-02 04:52:31.940 elif tag == 'delete':
2025-07-02 04:52:31.940 atags += '-' * la
2025-07-02 04:52:31.940 elif tag == 'insert':
2025-07-02 04:52:31.940 btags += '+' * lb
2025-07-02 04:52:31.940 elif tag == 'equal':
2025-07-02 04:52:31.940 atags += ' ' * la
2025-07-02 04:52:31.940 btags += ' ' * lb
2025-07-02 04:52:31.940 else:
2025-07-02 04:52:31.940 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.940 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.940 else:
2025-07-02 04:52:31.940 # the synch pair is identical
2025-07-02 04:52:31.940 yield ' ' + aelt
2025-07-02 04:52:31.940
2025-07-02 04:52:31.940 # pump out diffs from after the synch point
2025-07-02 04:52:31.940 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.940
2025-07-02 04:52:31.941 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.941 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.941
2025-07-02 04:52:31.941 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.941 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.941 alo = 136, ahi = 1101
2025-07-02 04:52:31.941 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.941 blo = 136, bhi = 1101
2025-07-02 04:52:31.941
2025-07-02 04:52:31.941 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.941 g = []
2025-07-02 04:52:31.941 if alo < ahi:
2025-07-02 04:52:31.941 if blo < bhi:
2025-07-02 04:52:31.941 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.941 else:
2025-07-02 04:52:31.941 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.941 elif blo < bhi:
2025-07-02 04:52:31.941 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.941
2025-07-02 04:52:31.941 > yield from g
2025-07-02 04:52:31.941
2025-07-02 04:52:31.942 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.942 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.942
2025-07-02 04:52:31.942 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.942 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.942 alo = 136, ahi = 1101
2025-07-02 04:52:31.942 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.942 blo = 136, bhi = 1101
2025-07-02 04:52:31.942
2025-07-02 04:52:31.942 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.942 r"""
2025-07-02 04:52:31.942 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.942 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.942 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.942 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.942
2025-07-02 04:52:31.942 Example:
2025-07-02 04:52:31.942
2025-07-02 04:52:31.942 >>> d = Differ()
2025-07-02 04:52:31.943 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.943 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.943 >>> print(''.join(results), end="")
2025-07-02 04:52:31.943 - abcDefghiJkl
2025-07-02 04:52:31.943 + abcdefGhijkl
2025-07-02 04:52:31.943 """
2025-07-02 04:52:31.943
2025-07-02 04:52:31.943 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.943 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.943 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.943 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.943 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.943
2025-07-02 04:52:31.943 # search for the pair that matches best without being identical
2025-07-02 04:52:31.943 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.943 # on junk -- unless we have to)
2025-07-02 04:52:31.943 for j in range(blo, bhi):
2025-07-02 04:52:31.943 bj = b[j]
2025-07-02 04:52:31.944 cruncher.set_seq2(bj)
2025-07-02 04:52:31.944 for i in range(alo, ahi):
2025-07-02 04:52:31.944 ai = a[i]
2025-07-02 04:52:31.944 if ai == bj:
2025-07-02 04:52:31.944 if eqi is None:
2025-07-02 04:52:31.944 eqi, eqj = i, j
2025-07-02 04:52:31.944 continue
2025-07-02 04:52:31.944 cruncher.set_seq1(ai)
2025-07-02 04:52:31.944 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.944 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.944 # compares by a factor of 3.
2025-07-02 04:52:31.944 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.944 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.944 # of the computation is cached by cruncher
2025-07-02 04:52:31.944 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.944 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.944 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.944 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.944 if best_ratio < cutoff:
2025-07-02 04:52:31.944 # no non-identical "pretty close" pair
2025-07-02 04:52:31.945 if eqi is None:
2025-07-02 04:52:31.945 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.945 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.945 return
2025-07-02 04:52:31.945 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.945 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.945 else:
2025-07-02 04:52:31.945 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.945 eqi = None
2025-07-02 04:52:31.945
2025-07-02 04:52:31.945 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.945 # identical
2025-07-02 04:52:31.945
2025-07-02 04:52:31.945 # pump out diffs from before the synch point
2025-07-02 04:52:31.945 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.945
2025-07-02 04:52:31.945 # do intraline marking on the synch pair
2025-07-02 04:52:31.945 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.945 if eqi is None:
2025-07-02 04:52:31.945 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.946 atags = btags = ""
2025-07-02 04:52:31.946 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.946 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.946 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.946 if tag == 'replace':
2025-07-02 04:52:31.946 atags += '^' * la
2025-07-02 04:52:31.946 btags += '^' * lb
2025-07-02 04:52:31.946 elif tag == 'delete':
2025-07-02 04:52:31.946 atags += '-' * la
2025-07-02 04:52:31.946 elif tag == 'insert':
2025-07-02 04:52:31.946 btags += '+' * lb
2025-07-02 04:52:31.946 elif tag == 'equal':
2025-07-02 04:52:31.946 atags += ' ' * la
2025-07-02 04:52:31.946 btags += ' ' * lb
2025-07-02 04:52:31.946 else:
2025-07-02 04:52:31.946 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.946 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.946 else:
2025-07-02 04:52:31.946 # the synch pair is identical
2025-07-02 04:52:31.946 yield ' ' + aelt
2025-07-02 04:52:31.946
2025-07-02 04:52:31.946 # pump out diffs from after the synch point
2025-07-02 04:52:31.947 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.947
2025-07-02 04:52:31.947 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.947 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.947
2025-07-02 04:52:31.947 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.947 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.947 alo = 137, ahi = 1101
2025-07-02 04:52:31.947 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.947 blo = 137, bhi = 1101
2025-07-02 04:52:31.947
2025-07-02 04:52:31.947 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.947 g = []
2025-07-02 04:52:31.947 if alo < ahi:
2025-07-02 04:52:31.947 if blo < bhi:
2025-07-02 04:52:31.947 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.947 else:
2025-07-02 04:52:31.947 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.947 elif blo < bhi:
2025-07-02 04:52:31.947 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.948
2025-07-02 04:52:31.948 > yield from g
2025-07-02 04:52:31.948
2025-07-02 04:52:31.948 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.948 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.948
2025-07-02 04:52:31.948 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.948 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.948 alo = 137, ahi = 1101
2025-07-02 04:52:31.948 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.948 blo = 137, bhi = 1101
2025-07-02 04:52:31.948
2025-07-02 04:52:31.948 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.948 r"""
2025-07-02 04:52:31.948 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.948 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.948 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.948 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.948
2025-07-02 04:52:31.948 Example:
2025-07-02 04:52:31.948
2025-07-02 04:52:31.949 >>> d = Differ()
2025-07-02 04:52:31.949 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.949 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.949 >>> print(''.join(results), end="")
2025-07-02 04:52:31.949 - abcDefghiJkl
2025-07-02 04:52:31.949 + abcdefGhijkl
2025-07-02 04:52:31.949 """
2025-07-02 04:52:31.949
2025-07-02 04:52:31.949 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.949 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.949 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.949 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.949 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.949
2025-07-02 04:52:31.949 # search for the pair that matches best without being identical
2025-07-02 04:52:31.949 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.949 # on junk -- unless we have to)
2025-07-02 04:52:31.949 for j in range(blo, bhi):
2025-07-02 04:52:31.949 bj = b[j]
2025-07-02 04:52:31.950 cruncher.set_seq2(bj)
2025-07-02 04:52:31.950 for i in range(alo, ahi):
2025-07-02 04:52:31.950 ai = a[i]
2025-07-02 04:52:31.950 if ai == bj:
2025-07-02 04:52:31.950 if eqi is None:
2025-07-02 04:52:31.950 eqi, eqj = i, j
2025-07-02 04:52:31.950 continue
2025-07-02 04:52:31.950 cruncher.set_seq1(ai)
2025-07-02 04:52:31.950 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.950 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.950 # compares by a factor of 3.
2025-07-02 04:52:31.950 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.950 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.950 # of the computation is cached by cruncher
2025-07-02 04:52:31.950 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.950 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.950 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.950 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.950 if best_ratio < cutoff:
2025-07-02 04:52:31.950 # no non-identical "pretty close" pair
2025-07-02 04:52:31.950 if eqi is None:
2025-07-02 04:52:31.950 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.951 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.951 return
2025-07-02 04:52:31.951 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.951 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.951 else:
2025-07-02 04:52:31.951 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.951 eqi = None
2025-07-02 04:52:31.951
2025-07-02 04:52:31.951 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.951 # identical
2025-07-02 04:52:31.951
2025-07-02 04:52:31.951 # pump out diffs from before the synch point
2025-07-02 04:52:31.951 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.951
2025-07-02 04:52:31.951 # do intraline marking on the synch pair
2025-07-02 04:52:31.951 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.951 if eqi is None:
2025-07-02 04:52:31.951 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.951 atags = btags = ""
2025-07-02 04:52:31.951 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.951 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.952 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.952 if tag == 'replace':
2025-07-02 04:52:31.952 atags += '^' * la
2025-07-02 04:52:31.952 btags += '^' * lb
2025-07-02 04:52:31.952 elif tag == 'delete':
2025-07-02 04:52:31.952 atags += '-' * la
2025-07-02 04:52:31.952 elif tag == 'insert':
2025-07-02 04:52:31.952 btags += '+' * lb
2025-07-02 04:52:31.952 elif tag == 'equal':
2025-07-02 04:52:31.952 atags += ' ' * la
2025-07-02 04:52:31.952 btags += ' ' * lb
2025-07-02 04:52:31.952 else:
2025-07-02 04:52:31.952 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.952 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.952 else:
2025-07-02 04:52:31.952 # the synch pair is identical
2025-07-02 04:52:31.952 yield ' ' + aelt
2025-07-02 04:52:31.952
2025-07-02 04:52:31.952 # pump out diffs from after the synch point
2025-07-02 04:52:31.952 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.953
2025-07-02 04:52:31.953 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.953 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.953
2025-07-02 04:52:31.953 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.953 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.953 alo = 138, ahi = 1101
2025-07-02 04:52:31.953 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.953 blo = 138, bhi = 1101
2025-07-02 04:52:31.953
2025-07-02 04:52:31.953 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.953 g = []
2025-07-02 04:52:31.953 if alo < ahi:
2025-07-02 04:52:31.953 if blo < bhi:
2025-07-02 04:52:31.953 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.953 else:
2025-07-02 04:52:31.953 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.953 elif blo < bhi:
2025-07-02 04:52:31.953 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.953
2025-07-02 04:52:31.954 > yield from g
2025-07-02 04:52:31.954
2025-07-02 04:52:31.954 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.954 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.954
2025-07-02 04:52:31.954 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.954 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.954 alo = 138, ahi = 1101
2025-07-02 04:52:31.954 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.954 blo = 138, bhi = 1101
2025-07-02 04:52:31.954
2025-07-02 04:52:31.954 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.954 r"""
2025-07-02 04:52:31.954 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.954 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.954 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.954 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.954
2025-07-02 04:52:31.954 Example:
2025-07-02 04:52:31.954
2025-07-02 04:52:31.954 >>> d = Differ()
2025-07-02 04:52:31.955 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.955 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.955 >>> print(''.join(results), end="")
2025-07-02 04:52:31.955 - abcDefghiJkl
2025-07-02 04:52:31.955 + abcdefGhijkl
2025-07-02 04:52:31.955 """
2025-07-02 04:52:31.955
2025-07-02 04:52:31.955 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.955 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.955 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.955 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.955 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.955
2025-07-02 04:52:31.955 # search for the pair that matches best without being identical
2025-07-02 04:52:31.955 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.955 # on junk -- unless we have to)
2025-07-02 04:52:31.955 for j in range(blo, bhi):
2025-07-02 04:52:31.955 bj = b[j]
2025-07-02 04:52:31.955 cruncher.set_seq2(bj)
2025-07-02 04:52:31.955 for i in range(alo, ahi):
2025-07-02 04:52:31.956 ai = a[i]
2025-07-02 04:52:31.956 if ai == bj:
2025-07-02 04:52:31.956 if eqi is None:
2025-07-02 04:52:31.956 eqi, eqj = i, j
2025-07-02 04:52:31.956 continue
2025-07-02 04:52:31.956 cruncher.set_seq1(ai)
2025-07-02 04:52:31.956 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.956 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.956 # compares by a factor of 3.
2025-07-02 04:52:31.956 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.956 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.956 # of the computation is cached by cruncher
2025-07-02 04:52:31.956 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.956 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.956 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.956 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.956 if best_ratio < cutoff:
2025-07-02 04:52:31.956 # no non-identical "pretty close" pair
2025-07-02 04:52:31.956 if eqi is None:
2025-07-02 04:52:31.956 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.956 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.957 return
2025-07-02 04:52:31.957 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.957 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.957 else:
2025-07-02 04:52:31.957 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.957 eqi = None
2025-07-02 04:52:31.957
2025-07-02 04:52:31.957 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.957 # identical
2025-07-02 04:52:31.957
2025-07-02 04:52:31.957 # pump out diffs from before the synch point
2025-07-02 04:52:31.957 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.957
2025-07-02 04:52:31.957 # do intraline marking on the synch pair
2025-07-02 04:52:31.957 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.957 if eqi is None:
2025-07-02 04:52:31.957 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.957 atags = btags = ""
2025-07-02 04:52:31.957 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.957 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.957 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.957 if tag == 'replace':
2025-07-02 04:52:31.958 atags += '^' * la
2025-07-02 04:52:31.958 btags += '^' * lb
2025-07-02 04:52:31.958 elif tag == 'delete':
2025-07-02 04:52:31.958 atags += '-' * la
2025-07-02 04:52:31.958 elif tag == 'insert':
2025-07-02 04:52:31.958 btags += '+' * lb
2025-07-02 04:52:31.958 elif tag == 'equal':
2025-07-02 04:52:31.958 atags += ' ' * la
2025-07-02 04:52:31.958 btags += ' ' * lb
2025-07-02 04:52:31.958 else:
2025-07-02 04:52:31.958 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.958 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.958 else:
2025-07-02 04:52:31.958 # the synch pair is identical
2025-07-02 04:52:31.958 yield ' ' + aelt
2025-07-02 04:52:31.958
2025-07-02 04:52:31.958 # pump out diffs from after the synch point
2025-07-02 04:52:31.958 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.958
2025-07-02 04:52:31.958 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.958 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.959
2025-07-02 04:52:31.959 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.959 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.959 alo = 139, ahi = 1101
2025-07-02 04:52:31.959 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.959 blo = 139, bhi = 1101
2025-07-02 04:52:31.959
2025-07-02 04:52:31.959 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.959 g = []
2025-07-02 04:52:31.959 if alo < ahi:
2025-07-02 04:52:31.959 if blo < bhi:
2025-07-02 04:52:31.959 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.959 else:
2025-07-02 04:52:31.959 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.959 elif blo < bhi:
2025-07-02 04:52:31.959 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.959
2025-07-02 04:52:31.959 > yield from g
2025-07-02 04:52:31.959
2025-07-02 04:52:31.959 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.959 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.960
2025-07-02 04:52:31.960 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.960 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.960 alo = 139, ahi = 1101
2025-07-02 04:52:31.960 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.960 blo = 139, bhi = 1101
2025-07-02 04:52:31.960
2025-07-02 04:52:31.960 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.960 r"""
2025-07-02 04:52:31.960 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.960 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.960 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.960 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.960
2025-07-02 04:52:31.960 Example:
2025-07-02 04:52:31.960
2025-07-02 04:52:31.960 >>> d = Differ()
2025-07-02 04:52:31.960 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.961 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.961 >>> print(''.join(results), end="")
2025-07-02 04:52:31.961 - abcDefghiJkl
2025-07-02 04:52:31.961 + abcdefGhijkl
2025-07-02 04:52:31.961 """
2025-07-02 04:52:31.961
2025-07-02 04:52:31.961 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.961 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.961 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.961 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.961 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.961
2025-07-02 04:52:31.961 # search for the pair that matches best without being identical
2025-07-02 04:52:31.961 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.961 # on junk -- unless we have to)
2025-07-02 04:52:31.961 for j in range(blo, bhi):
2025-07-02 04:52:31.961 bj = b[j]
2025-07-02 04:52:31.961 cruncher.set_seq2(bj)
2025-07-02 04:52:31.962 for i in range(alo, ahi):
2025-07-02 04:52:31.962 ai = a[i]
2025-07-02 04:52:31.962 if ai == bj:
2025-07-02 04:52:31.962 if eqi is None:
2025-07-02 04:52:31.962 eqi, eqj = i, j
2025-07-02 04:52:31.962 continue
2025-07-02 04:52:31.962 cruncher.set_seq1(ai)
2025-07-02 04:52:31.962 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.962 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.962 # compares by a factor of 3.
2025-07-02 04:52:31.962 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.962 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.962 # of the computation is cached by cruncher
2025-07-02 04:52:31.962 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.962 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.962 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.962 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.962 if best_ratio < cutoff:
2025-07-02 04:52:31.962 # no non-identical "pretty close" pair
2025-07-02 04:52:31.962 if eqi is None:
2025-07-02 04:52:31.962 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.963 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.963 return
2025-07-02 04:52:31.963 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.963 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.963 else:
2025-07-02 04:52:31.963 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.963 eqi = None
2025-07-02 04:52:31.963
2025-07-02 04:52:31.963 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.963 # identical
2025-07-02 04:52:31.963
2025-07-02 04:52:31.963 # pump out diffs from before the synch point
2025-07-02 04:52:31.963 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.963
2025-07-02 04:52:31.963 # do intraline marking on the synch pair
2025-07-02 04:52:31.963 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.963 if eqi is None:
2025-07-02 04:52:31.963 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.963 atags = btags = ""
2025-07-02 04:52:31.964 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.964 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.964 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.964 if tag == 'replace':
2025-07-02 04:52:31.964 atags += '^' * la
2025-07-02 04:52:31.964 btags += '^' * lb
2025-07-02 04:52:31.964 elif tag == 'delete':
2025-07-02 04:52:31.964 atags += '-' * la
2025-07-02 04:52:31.964 elif tag == 'insert':
2025-07-02 04:52:31.964 btags += '+' * lb
2025-07-02 04:52:31.964 elif tag == 'equal':
2025-07-02 04:52:31.964 atags += ' ' * la
2025-07-02 04:52:31.964 btags += ' ' * lb
2025-07-02 04:52:31.964 else:
2025-07-02 04:52:31.964 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.964 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.964 else:
2025-07-02 04:52:31.964 # the synch pair is identical
2025-07-02 04:52:31.964 yield ' ' + aelt
2025-07-02 04:52:31.964
2025-07-02 04:52:31.964 # pump out diffs from after the synch point
2025-07-02 04:52:31.965 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.965
2025-07-02 04:52:31.965 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.965 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.965
2025-07-02 04:52:31.965 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.965 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.965 alo = 140, ahi = 1101
2025-07-02 04:52:31.965 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.965 blo = 140, bhi = 1101
2025-07-02 04:52:31.965
2025-07-02 04:52:31.965 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.965 g = []
2025-07-02 04:52:31.965 if alo < ahi:
2025-07-02 04:52:31.965 if blo < bhi:
2025-07-02 04:52:31.965 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.965 else:
2025-07-02 04:52:31.965 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.965 elif blo < bhi:
2025-07-02 04:52:31.965 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.965
2025-07-02 04:52:31.966 > yield from g
2025-07-02 04:52:31.966
2025-07-02 04:52:31.966 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.966 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.966
2025-07-02 04:52:31.966 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.966 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.966 alo = 140, ahi = 1101
2025-07-02 04:52:31.966 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.966 blo = 140, bhi = 1101
2025-07-02 04:52:31.966
2025-07-02 04:52:31.966 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.966 r"""
2025-07-02 04:52:31.966 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.966 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.966 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.966 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.966
2025-07-02 04:52:31.966 Example:
2025-07-02 04:52:31.966
2025-07-02 04:52:31.967 >>> d = Differ()
2025-07-02 04:52:31.967 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.967 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.967 >>> print(''.join(results), end="")
2025-07-02 04:52:31.967 - abcDefghiJkl
2025-07-02 04:52:31.967 + abcdefGhijkl
2025-07-02 04:52:31.967 """
2025-07-02 04:52:31.967
2025-07-02 04:52:31.967 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.967 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.967 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.967 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.967 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.967
2025-07-02 04:52:31.967 # search for the pair that matches best without being identical
2025-07-02 04:52:31.967 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.967 # on junk -- unless we have to)
2025-07-02 04:52:31.967 for j in range(blo, bhi):
2025-07-02 04:52:31.967 bj = b[j]
2025-07-02 04:52:31.967 cruncher.set_seq2(bj)
2025-07-02 04:52:31.968 for i in range(alo, ahi):
2025-07-02 04:52:31.968 ai = a[i]
2025-07-02 04:52:31.968 if ai == bj:
2025-07-02 04:52:31.968 if eqi is None:
2025-07-02 04:52:31.968 eqi, eqj = i, j
2025-07-02 04:52:31.968 continue
2025-07-02 04:52:31.968 cruncher.set_seq1(ai)
2025-07-02 04:52:31.968 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.968 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.968 # compares by a factor of 3.
2025-07-02 04:52:31.968 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.968 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.968 # of the computation is cached by cruncher
2025-07-02 04:52:31.968 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.968 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.968 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.968 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.968 if best_ratio < cutoff:
2025-07-02 04:52:31.968 # no non-identical "pretty close" pair
2025-07-02 04:52:31.968 if eqi is None:
2025-07-02 04:52:31.969 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.969 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.969 return
2025-07-02 04:52:31.969 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.969 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.969 else:
2025-07-02 04:52:31.969 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.969 eqi = None
2025-07-02 04:52:31.969
2025-07-02 04:52:31.969 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.969 # identical
2025-07-02 04:52:31.969
2025-07-02 04:52:31.969 # pump out diffs from before the synch point
2025-07-02 04:52:31.969 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.969
2025-07-02 04:52:31.969 # do intraline marking on the synch pair
2025-07-02 04:52:31.969 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.969 if eqi is None:
2025-07-02 04:52:31.969 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.970 atags = btags = ""
2025-07-02 04:52:31.970 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.970 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.970 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.970 if tag == 'replace':
2025-07-02 04:52:31.970 atags += '^' * la
2025-07-02 04:52:31.970 btags += '^' * lb
2025-07-02 04:52:31.970 elif tag == 'delete':
2025-07-02 04:52:31.970 atags += '-' * la
2025-07-02 04:52:31.970 elif tag == 'insert':
2025-07-02 04:52:31.970 btags += '+' * lb
2025-07-02 04:52:31.970 elif tag == 'equal':
2025-07-02 04:52:31.970 atags += ' ' * la
2025-07-02 04:52:31.970 btags += ' ' * lb
2025-07-02 04:52:31.970 else:
2025-07-02 04:52:31.970 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.970 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.970 else:
2025-07-02 04:52:31.970 # the synch pair is identical
2025-07-02 04:52:31.970 yield ' ' + aelt
2025-07-02 04:52:31.970
2025-07-02 04:52:31.971 # pump out diffs from after the synch point
2025-07-02 04:52:31.971 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.971
2025-07-02 04:52:31.971 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.971 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.971
2025-07-02 04:52:31.971 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.971 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.971 alo = 141, ahi = 1101
2025-07-02 04:52:31.971 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.971 blo = 141, bhi = 1101
2025-07-02 04:52:31.971
2025-07-02 04:52:31.971 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.971 g = []
2025-07-02 04:52:31.971 if alo < ahi:
2025-07-02 04:52:31.971 if blo < bhi:
2025-07-02 04:52:31.971 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.971 else:
2025-07-02 04:52:31.971 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.971 elif blo < bhi:
2025-07-02 04:52:31.971 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.972
2025-07-02 04:52:31.972 > yield from g
2025-07-02 04:52:31.972
2025-07-02 04:52:31.972 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.972 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.972
2025-07-02 04:52:31.972 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.972 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.972 alo = 141, ahi = 1101
2025-07-02 04:52:31.972 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.972 blo = 141, bhi = 1101
2025-07-02 04:52:31.972
2025-07-02 04:52:31.972 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.972 r"""
2025-07-02 04:52:31.972 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.972 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.972 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.972 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.972
2025-07-02 04:52:31.972 Example:
2025-07-02 04:52:31.972
2025-07-02 04:52:31.972 >>> d = Differ()
2025-07-02 04:52:31.973 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.973 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.973 >>> print(''.join(results), end="")
2025-07-02 04:52:31.973 - abcDefghiJkl
2025-07-02 04:52:31.973 + abcdefGhijkl
2025-07-02 04:52:31.973 """
2025-07-02 04:52:31.973
2025-07-02 04:52:31.973 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.973 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.973 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.973 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.973 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.973
2025-07-02 04:52:31.973 # search for the pair that matches best without being identical
2025-07-02 04:52:31.973 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.973 # on junk -- unless we have to)
2025-07-02 04:52:31.973 for j in range(blo, bhi):
2025-07-02 04:52:31.973 bj = b[j]
2025-07-02 04:52:31.973 cruncher.set_seq2(bj)
2025-07-02 04:52:31.974 for i in range(alo, ahi):
2025-07-02 04:52:31.974 ai = a[i]
2025-07-02 04:52:31.974 if ai == bj:
2025-07-02 04:52:31.974 if eqi is None:
2025-07-02 04:52:31.974 eqi, eqj = i, j
2025-07-02 04:52:31.974 continue
2025-07-02 04:52:31.974 cruncher.set_seq1(ai)
2025-07-02 04:52:31.974 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.974 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.974 # compares by a factor of 3.
2025-07-02 04:52:31.974 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.974 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.974 # of the computation is cached by cruncher
2025-07-02 04:52:31.974 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.974 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.974 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.974 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.974 if best_ratio < cutoff:
2025-07-02 04:52:31.974 # no non-identical "pretty close" pair
2025-07-02 04:52:31.974 if eqi is None:
2025-07-02 04:52:31.974 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.974 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.975 return
2025-07-02 04:52:31.975 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.975 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.975 else:
2025-07-02 04:52:31.975 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.975 eqi = None
2025-07-02 04:52:31.975
2025-07-02 04:52:31.975 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.975 # identical
2025-07-02 04:52:31.975
2025-07-02 04:52:31.975 # pump out diffs from before the synch point
2025-07-02 04:52:31.975 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.975
2025-07-02 04:52:31.975 # do intraline marking on the synch pair
2025-07-02 04:52:31.975 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.975 if eqi is None:
2025-07-02 04:52:31.975 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.975 atags = btags = ""
2025-07-02 04:52:31.975 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.975 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.975 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.976 if tag == 'replace':
2025-07-02 04:52:31.976 atags += '^' * la
2025-07-02 04:52:31.976 btags += '^' * lb
2025-07-02 04:52:31.976 elif tag == 'delete':
2025-07-02 04:52:31.976 atags += '-' * la
2025-07-02 04:52:31.976 elif tag == 'insert':
2025-07-02 04:52:31.976 btags += '+' * lb
2025-07-02 04:52:31.976 elif tag == 'equal':
2025-07-02 04:52:31.976 atags += ' ' * la
2025-07-02 04:52:31.976 btags += ' ' * lb
2025-07-02 04:52:31.976 else:
2025-07-02 04:52:31.976 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.976 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.976 else:
2025-07-02 04:52:31.976 # the synch pair is identical
2025-07-02 04:52:31.976 yield ' ' + aelt
2025-07-02 04:52:31.976
2025-07-02 04:52:31.976 # pump out diffs from after the synch point
2025-07-02 04:52:31.976 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.976
2025-07-02 04:52:31.977 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.977 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.977
2025-07-02 04:52:31.977 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.977 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.977 alo = 142, ahi = 1101
2025-07-02 04:52:31.977 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.977 blo = 142, bhi = 1101
2025-07-02 04:52:31.977
2025-07-02 04:52:31.977 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.977 g = []
2025-07-02 04:52:31.977 if alo < ahi:
2025-07-02 04:52:31.977 if blo < bhi:
2025-07-02 04:52:31.977 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.977 else:
2025-07-02 04:52:31.977 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.977 elif blo < bhi:
2025-07-02 04:52:31.977 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.977
2025-07-02 04:52:31.978 > yield from g
2025-07-02 04:52:31.978
2025-07-02 04:52:31.978 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.978 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.978
2025-07-02 04:52:31.978 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.978 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.978 alo = 142, ahi = 1101
2025-07-02 04:52:31.978 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.978 blo = 142, bhi = 1101
2025-07-02 04:52:31.978
2025-07-02 04:52:31.978 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.978 r"""
2025-07-02 04:52:31.978 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.978 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.978 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.978 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.978
2025-07-02 04:52:31.978 Example:
2025-07-02 04:52:31.978
2025-07-02 04:52:31.979 >>> d = Differ()
2025-07-02 04:52:31.979 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.979 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.979 >>> print(''.join(results), end="")
2025-07-02 04:52:31.979 - abcDefghiJkl
2025-07-02 04:52:31.979 + abcdefGhijkl
2025-07-02 04:52:31.979 """
2025-07-02 04:52:31.979
2025-07-02 04:52:31.979 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.979 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.979 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.979 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.979 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.979
2025-07-02 04:52:31.979 # search for the pair that matches best without being identical
2025-07-02 04:52:31.979 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.979 # on junk -- unless we have to)
2025-07-02 04:52:31.979 for j in range(blo, bhi):
2025-07-02 04:52:31.979 bj = b[j]
2025-07-02 04:52:31.979 cruncher.set_seq2(bj)
2025-07-02 04:52:31.980 for i in range(alo, ahi):
2025-07-02 04:52:31.980 ai = a[i]
2025-07-02 04:52:31.980 if ai == bj:
2025-07-02 04:52:31.980 if eqi is None:
2025-07-02 04:52:31.980 eqi, eqj = i, j
2025-07-02 04:52:31.980 continue
2025-07-02 04:52:31.980 cruncher.set_seq1(ai)
2025-07-02 04:52:31.980 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.980 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.980 # compares by a factor of 3.
2025-07-02 04:52:31.980 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.980 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.980 # of the computation is cached by cruncher
2025-07-02 04:52:31.980 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.980 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.980 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.980 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.980 if best_ratio < cutoff:
2025-07-02 04:52:31.980 # no non-identical "pretty close" pair
2025-07-02 04:52:31.980 if eqi is None:
2025-07-02 04:52:31.980 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.980 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.980 return
2025-07-02 04:52:31.980 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.980 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.980 else:
2025-07-02 04:52:31.980 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.981 eqi = None
2025-07-02 04:52:31.981
2025-07-02 04:52:31.981 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.981 # identical
2025-07-02 04:52:31.981
2025-07-02 04:52:31.981 # pump out diffs from before the synch point
2025-07-02 04:52:31.981 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.981
2025-07-02 04:52:31.981 # do intraline marking on the synch pair
2025-07-02 04:52:31.981 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.981 if eqi is None:
2025-07-02 04:52:31.981 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.981 atags = btags = ""
2025-07-02 04:52:31.981 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.981 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.981 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.981 if tag == 'replace':
2025-07-02 04:52:31.981 atags += '^' * la
2025-07-02 04:52:31.981 btags += '^' * lb
2025-07-02 04:52:31.981 elif tag == 'delete':
2025-07-02 04:52:31.981 atags += '-' * la
2025-07-02 04:52:31.981 elif tag == 'insert':
2025-07-02 04:52:31.982 btags += '+' * lb
2025-07-02 04:52:31.982 elif tag == 'equal':
2025-07-02 04:52:31.982 atags += ' ' * la
2025-07-02 04:52:31.982 btags += ' ' * lb
2025-07-02 04:52:31.982 else:
2025-07-02 04:52:31.982 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.982 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.982 else:
2025-07-02 04:52:31.982 # the synch pair is identical
2025-07-02 04:52:31.982 yield ' ' + aelt
2025-07-02 04:52:31.982
2025-07-02 04:52:31.982 # pump out diffs from after the synch point
2025-07-02 04:52:31.982 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.982
2025-07-02 04:52:31.982 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.982 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.982
2025-07-02 04:52:31.982 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.982 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.982 alo = 143, ahi = 1101
2025-07-02 04:52:31.982 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.983 blo = 143, bhi = 1101
2025-07-02 04:52:31.983
2025-07-02 04:52:31.983 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.983 g = []
2025-07-02 04:52:31.983 if alo < ahi:
2025-07-02 04:52:31.983 if blo < bhi:
2025-07-02 04:52:31.983 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.983 else:
2025-07-02 04:52:31.983 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.983 elif blo < bhi:
2025-07-02 04:52:31.983 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.983
2025-07-02 04:52:31.983 > yield from g
2025-07-02 04:52:31.983
2025-07-02 04:52:31.983 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.983 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.983
2025-07-02 04:52:31.983 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.983 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.983 alo = 143, ahi = 1101
2025-07-02 04:52:31.983 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.984 blo = 143, bhi = 1101
2025-07-02 04:52:31.984
2025-07-02 04:52:31.984 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.984 r"""
2025-07-02 04:52:31.984 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.984 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.984 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.984 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.984
2025-07-02 04:52:31.984 Example:
2025-07-02 04:52:31.984
2025-07-02 04:52:31.984 >>> d = Differ()
2025-07-02 04:52:31.984 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.984 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.984 >>> print(''.join(results), end="")
2025-07-02 04:52:31.984 - abcDefghiJkl
2025-07-02 04:52:31.984 + abcdefGhijkl
2025-07-02 04:52:31.984 """
2025-07-02 04:52:31.984
2025-07-02 04:52:31.984 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.985 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.985 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.985 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.985 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.985
2025-07-02 04:52:31.985 # search for the pair that matches best without being identical
2025-07-02 04:52:31.985 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.985 # on junk -- unless we have to)
2025-07-02 04:52:31.985 for j in range(blo, bhi):
2025-07-02 04:52:31.985 bj = b[j]
2025-07-02 04:52:31.985 cruncher.set_seq2(bj)
2025-07-02 04:52:31.985 for i in range(alo, ahi):
2025-07-02 04:52:31.985 ai = a[i]
2025-07-02 04:52:31.985 if ai == bj:
2025-07-02 04:52:31.985 if eqi is None:
2025-07-02 04:52:31.985 eqi, eqj = i, j
2025-07-02 04:52:31.985 continue
2025-07-02 04:52:31.985 cruncher.set_seq1(ai)
2025-07-02 04:52:31.985 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.985 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.986 # compares by a factor of 3.
2025-07-02 04:52:31.986 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.986 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.986 # of the computation is cached by cruncher
2025-07-02 04:52:31.986 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.986 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.986 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.986 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.986 if best_ratio < cutoff:
2025-07-02 04:52:31.986 # no non-identical "pretty close" pair
2025-07-02 04:52:31.986 if eqi is None:
2025-07-02 04:52:31.986 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.986 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.986 return
2025-07-02 04:52:31.986 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.986 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.986 else:
2025-07-02 04:52:31.986 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.986 eqi = None
2025-07-02 04:52:31.986
2025-07-02 04:52:31.986 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.987 # identical
2025-07-02 04:52:31.987
2025-07-02 04:52:31.987 # pump out diffs from before the synch point
2025-07-02 04:52:31.987 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.987
2025-07-02 04:52:31.987 # do intraline marking on the synch pair
2025-07-02 04:52:31.987 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.987 if eqi is None:
2025-07-02 04:52:31.987 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.987 atags = btags = ""
2025-07-02 04:52:31.987 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.987 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.987 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.987 if tag == 'replace':
2025-07-02 04:52:31.987 atags += '^' * la
2025-07-02 04:52:31.987 btags += '^' * lb
2025-07-02 04:52:31.987 elif tag == 'delete':
2025-07-02 04:52:31.987 atags += '-' * la
2025-07-02 04:52:31.987 elif tag == 'insert':
2025-07-02 04:52:31.987 btags += '+' * lb
2025-07-02 04:52:31.987 elif tag == 'equal':
2025-07-02 04:52:31.988 atags += ' ' * la
2025-07-02 04:52:31.988 btags += ' ' * lb
2025-07-02 04:52:31.988 else:
2025-07-02 04:52:31.988 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.988 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.988 else:
2025-07-02 04:52:31.988 # the synch pair is identical
2025-07-02 04:52:31.988 yield ' ' + aelt
2025-07-02 04:52:31.988
2025-07-02 04:52:31.988 # pump out diffs from after the synch point
2025-07-02 04:52:31.988 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.988
2025-07-02 04:52:31.988 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.988 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.988
2025-07-02 04:52:31.988 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.988 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.988 alo = 144, ahi = 1101
2025-07-02 04:52:31.988 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.988 blo = 144, bhi = 1101
2025-07-02 04:52:31.988
2025-07-02 04:52:31.989 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.989 g = []
2025-07-02 04:52:31.989 if alo < ahi:
2025-07-02 04:52:31.989 if blo < bhi:
2025-07-02 04:52:31.989 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.989 else:
2025-07-02 04:52:31.989 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.989 elif blo < bhi:
2025-07-02 04:52:31.989 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.989
2025-07-02 04:52:31.989 > yield from g
2025-07-02 04:52:31.989
2025-07-02 04:52:31.989 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.989 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.989
2025-07-02 04:52:31.989 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.989 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.989 alo = 144, ahi = 1101
2025-07-02 04:52:31.989 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.989 blo = 144, bhi = 1101
2025-07-02 04:52:31.989
2025-07-02 04:52:31.990 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.990 r"""
2025-07-02 04:52:31.990 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.990 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.990 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.990 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.990
2025-07-02 04:52:31.990 Example:
2025-07-02 04:52:31.990
2025-07-02 04:52:31.990 >>> d = Differ()
2025-07-02 04:52:31.990 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.990 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.990 >>> print(''.join(results), end="")
2025-07-02 04:52:31.990 - abcDefghiJkl
2025-07-02 04:52:31.990 + abcdefGhijkl
2025-07-02 04:52:31.990 """
2025-07-02 04:52:31.990
2025-07-02 04:52:31.990 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.990 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.990 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.991 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.991 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.991
2025-07-02 04:52:31.991 # search for the pair that matches best without being identical
2025-07-02 04:52:31.991 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.991 # on junk -- unless we have to)
2025-07-02 04:52:31.991 for j in range(blo, bhi):
2025-07-02 04:52:31.991 bj = b[j]
2025-07-02 04:52:31.991 cruncher.set_seq2(bj)
2025-07-02 04:52:31.991 for i in range(alo, ahi):
2025-07-02 04:52:31.991 ai = a[i]
2025-07-02 04:52:31.991 if ai == bj:
2025-07-02 04:52:31.991 if eqi is None:
2025-07-02 04:52:31.991 eqi, eqj = i, j
2025-07-02 04:52:31.991 continue
2025-07-02 04:52:31.991 cruncher.set_seq1(ai)
2025-07-02 04:52:31.991 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.991 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.992 # compares by a factor of 3.
2025-07-02 04:52:31.992 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.992 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.992 # of the computation is cached by cruncher
2025-07-02 04:52:31.992 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.992 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.992 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.992 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.992 if best_ratio < cutoff:
2025-07-02 04:52:31.992 # no non-identical "pretty close" pair
2025-07-02 04:52:31.992 if eqi is None:
2025-07-02 04:52:31.992 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.992 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.992 return
2025-07-02 04:52:31.992 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.992 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.992 else:
2025-07-02 04:52:31.992 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.992 eqi = None
2025-07-02 04:52:31.992
2025-07-02 04:52:31.992 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.993 # identical
2025-07-02 04:52:31.993
2025-07-02 04:52:31.993 # pump out diffs from before the synch point
2025-07-02 04:52:31.993 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.993
2025-07-02 04:52:31.993 # do intraline marking on the synch pair
2025-07-02 04:52:31.993 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.993 if eqi is None:
2025-07-02 04:52:31.993 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.993 atags = btags = ""
2025-07-02 04:52:31.993 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.993 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.993 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.993 if tag == 'replace':
2025-07-02 04:52:31.993 atags += '^' * la
2025-07-02 04:52:31.993 btags += '^' * lb
2025-07-02 04:52:31.993 elif tag == 'delete':
2025-07-02 04:52:31.993 atags += '-' * la
2025-07-02 04:52:31.993 elif tag == 'insert':
2025-07-02 04:52:31.993 btags += '+' * lb
2025-07-02 04:52:31.994 elif tag == 'equal':
2025-07-02 04:52:31.994 atags += ' ' * la
2025-07-02 04:52:31.994 btags += ' ' * lb
2025-07-02 04:52:31.994 else:
2025-07-02 04:52:31.994 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:31.994 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:31.994 else:
2025-07-02 04:52:31.994 # the synch pair is identical
2025-07-02 04:52:31.994 yield ' ' + aelt
2025-07-02 04:52:31.994
2025-07-02 04:52:31.994 # pump out diffs from after the synch point
2025-07-02 04:52:31.994 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:31.994
2025-07-02 04:52:31.994 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:31.994 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.994
2025-07-02 04:52:31.994 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.994 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.994 alo = 145, ahi = 1101
2025-07-02 04:52:31.994 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.995 blo = 145, bhi = 1101
2025-07-02 04:52:31.995
2025-07-02 04:52:31.995 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.995 g = []
2025-07-02 04:52:31.995 if alo < ahi:
2025-07-02 04:52:31.995 if blo < bhi:
2025-07-02 04:52:31.995 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.995 else:
2025-07-02 04:52:31.995 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:31.995 elif blo < bhi:
2025-07-02 04:52:31.995 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:31.995
2025-07-02 04:52:31.995 > yield from g
2025-07-02 04:52:31.995
2025-07-02 04:52:31.995 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:31.995 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:31.995
2025-07-02 04:52:31.995 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:31.995 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:31.995 alo = 145, ahi = 1101
2025-07-02 04:52:31.995 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:31.996 blo = 145, bhi = 1101
2025-07-02 04:52:31.996
2025-07-02 04:52:31.996 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:31.996 r"""
2025-07-02 04:52:31.996 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:31.996 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:31.996 synch point, and intraline difference marking is done on the
2025-07-02 04:52:31.996 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:31.996
2025-07-02 04:52:31.996 Example:
2025-07-02 04:52:31.996
2025-07-02 04:52:31.996 >>> d = Differ()
2025-07-02 04:52:31.996 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:31.996 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:31.996 >>> print(''.join(results), end="")
2025-07-02 04:52:31.996 - abcDefghiJkl
2025-07-02 04:52:31.996 + abcdefGhijkl
2025-07-02 04:52:31.996 """
2025-07-02 04:52:31.996
2025-07-02 04:52:31.997 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:31.997 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:31.997 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:31.997 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:31.997 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:31.997
2025-07-02 04:52:31.997 # search for the pair that matches best without being identical
2025-07-02 04:52:31.997 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:31.997 # on junk -- unless we have to)
2025-07-02 04:52:31.997 for j in range(blo, bhi):
2025-07-02 04:52:31.997 bj = b[j]
2025-07-02 04:52:31.997 cruncher.set_seq2(bj)
2025-07-02 04:52:31.997 for i in range(alo, ahi):
2025-07-02 04:52:31.997 ai = a[i]
2025-07-02 04:52:31.997 if ai == bj:
2025-07-02 04:52:31.997 if eqi is None:
2025-07-02 04:52:31.997 eqi, eqj = i, j
2025-07-02 04:52:31.997 continue
2025-07-02 04:52:31.997 cruncher.set_seq1(ai)
2025-07-02 04:52:31.997 # computing similarity is expensive, so use the quick
2025-07-02 04:52:31.998 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:31.998 # compares by a factor of 3.
2025-07-02 04:52:31.998 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:31.998 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:31.998 # of the computation is cached by cruncher
2025-07-02 04:52:31.998 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:31.998 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:31.998 cruncher.ratio() > best_ratio:
2025-07-02 04:52:31.998 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:31.998 if best_ratio < cutoff:
2025-07-02 04:52:31.998 # no non-identical "pretty close" pair
2025-07-02 04:52:31.998 if eqi is None:
2025-07-02 04:52:31.998 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:31.998 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:31.998 return
2025-07-02 04:52:31.998 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:31.998 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:31.998 else:
2025-07-02 04:52:31.998 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:31.998 eqi = None
2025-07-02 04:52:31.998
2025-07-02 04:52:31.999 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:31.999 # identical
2025-07-02 04:52:31.999
2025-07-02 04:52:31.999 # pump out diffs from before the synch point
2025-07-02 04:52:31.999 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:31.999
2025-07-02 04:52:31.999 # do intraline marking on the synch pair
2025-07-02 04:52:31.999 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:31.999 if eqi is None:
2025-07-02 04:52:31.999 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:31.999 atags = btags = ""
2025-07-02 04:52:31.999 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:31.999 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:31.999 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:31.999 if tag == 'replace':
2025-07-02 04:52:31.999 atags += '^' * la
2025-07-02 04:52:31.999 btags += '^' * lb
2025-07-02 04:52:31.999 elif tag == 'delete':
2025-07-02 04:52:31.999 atags += '-' * la
2025-07-02 04:52:31.999 elif tag == 'insert':
2025-07-02 04:52:31.999 btags += '+' * lb
2025-07-02 04:52:32.000 elif tag == 'equal':
2025-07-02 04:52:32.000 atags += ' ' * la
2025-07-02 04:52:32.000 btags += ' ' * lb
2025-07-02 04:52:32.000 else:
2025-07-02 04:52:32.000 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.000 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.000 else:
2025-07-02 04:52:32.000 # the synch pair is identical
2025-07-02 04:52:32.000 yield ' ' + aelt
2025-07-02 04:52:32.000
2025-07-02 04:52:32.000 # pump out diffs from after the synch point
2025-07-02 04:52:32.000 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.000
2025-07-02 04:52:32.000 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.000 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.000
2025-07-02 04:52:32.000 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.000 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.000 alo = 146, ahi = 1101
2025-07-02 04:52:32.000 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.000 blo = 146, bhi = 1101
2025-07-02 04:52:32.000
2025-07-02 04:52:32.001 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.001 g = []
2025-07-02 04:52:32.001 if alo < ahi:
2025-07-02 04:52:32.001 if blo < bhi:
2025-07-02 04:52:32.001 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.001 else:
2025-07-02 04:52:32.001 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.001 elif blo < bhi:
2025-07-02 04:52:32.001 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.001
2025-07-02 04:52:32.001 > yield from g
2025-07-02 04:52:32.001
2025-07-02 04:52:32.001 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.001 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.001
2025-07-02 04:52:32.001 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.001 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.001 alo = 146, ahi = 1101
2025-07-02 04:52:32.001 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.001 blo = 146, bhi = 1101
2025-07-02 04:52:32.002
2025-07-02 04:52:32.002 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.002 r"""
2025-07-02 04:52:32.002 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.002 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.002 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.002 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.002
2025-07-02 04:52:32.002 Example:
2025-07-02 04:52:32.002
2025-07-02 04:52:32.002 >>> d = Differ()
2025-07-02 04:52:32.002 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.002 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.002 >>> print(''.join(results), end="")
2025-07-02 04:52:32.002 - abcDefghiJkl
2025-07-02 04:52:32.002 + abcdefGhijkl
2025-07-02 04:52:32.002 """
2025-07-02 04:52:32.002
2025-07-02 04:52:32.002 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.003 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.003 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.003 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.003 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.003
2025-07-02 04:52:32.003 # search for the pair that matches best without being identical
2025-07-02 04:52:32.003 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.003 # on junk -- unless we have to)
2025-07-02 04:52:32.003 for j in range(blo, bhi):
2025-07-02 04:52:32.003 bj = b[j]
2025-07-02 04:52:32.003 cruncher.set_seq2(bj)
2025-07-02 04:52:32.003 for i in range(alo, ahi):
2025-07-02 04:52:32.003 ai = a[i]
2025-07-02 04:52:32.003 if ai == bj:
2025-07-02 04:52:32.003 if eqi is None:
2025-07-02 04:52:32.003 eqi, eqj = i, j
2025-07-02 04:52:32.003 continue
2025-07-02 04:52:32.003 cruncher.set_seq1(ai)
2025-07-02 04:52:32.003 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.003 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.004 # compares by a factor of 3.
2025-07-02 04:52:32.004 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.004 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.004 # of the computation is cached by cruncher
2025-07-02 04:52:32.004 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.004 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.004 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.004 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.004 if best_ratio < cutoff:
2025-07-02 04:52:32.004 # no non-identical "pretty close" pair
2025-07-02 04:52:32.004 if eqi is None:
2025-07-02 04:52:32.004 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.004 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.004 return
2025-07-02 04:52:32.004 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.004 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.004 else:
2025-07-02 04:52:32.004 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.004 eqi = None
2025-07-02 04:52:32.004
2025-07-02 04:52:32.004 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.005 # identical
2025-07-02 04:52:32.005
2025-07-02 04:52:32.005 # pump out diffs from before the synch point
2025-07-02 04:52:32.005 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.005
2025-07-02 04:52:32.005 # do intraline marking on the synch pair
2025-07-02 04:52:32.005 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.005 if eqi is None:
2025-07-02 04:52:32.005 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.005 atags = btags = ""
2025-07-02 04:52:32.005 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.005 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.005 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.005 if tag == 'replace':
2025-07-02 04:52:32.005 atags += '^' * la
2025-07-02 04:52:32.005 btags += '^' * lb
2025-07-02 04:52:32.005 elif tag == 'delete':
2025-07-02 04:52:32.005 atags += '-' * la
2025-07-02 04:52:32.005 elif tag == 'insert':
2025-07-02 04:52:32.005 btags += '+' * lb
2025-07-02 04:52:32.005 elif tag == 'equal':
2025-07-02 04:52:32.005 atags += ' ' * la
2025-07-02 04:52:32.006 btags += ' ' * lb
2025-07-02 04:52:32.006 else:
2025-07-02 04:52:32.006 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.006 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.006 else:
2025-07-02 04:52:32.006 # the synch pair is identical
2025-07-02 04:52:32.006 yield ' ' + aelt
2025-07-02 04:52:32.006
2025-07-02 04:52:32.006 # pump out diffs from after the synch point
2025-07-02 04:52:32.006 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.006
2025-07-02 04:52:32.006 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.006 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.006
2025-07-02 04:52:32.006 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.006 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.006 alo = 147, ahi = 1101
2025-07-02 04:52:32.006 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.006 blo = 147, bhi = 1101
2025-07-02 04:52:32.006
2025-07-02 04:52:32.006 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.007 g = []
2025-07-02 04:52:32.007 if alo < ahi:
2025-07-02 04:52:32.007 if blo < bhi:
2025-07-02 04:52:32.007 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.007 else:
2025-07-02 04:52:32.007 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.007 elif blo < bhi:
2025-07-02 04:52:32.007 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.007
2025-07-02 04:52:32.007 > yield from g
2025-07-02 04:52:32.007
2025-07-02 04:52:32.007 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.007 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.007
2025-07-02 04:52:32.007 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.007 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.007 alo = 147, ahi = 1101
2025-07-02 04:52:32.007 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.007 blo = 147, bhi = 1101
2025-07-02 04:52:32.007
2025-07-02 04:52:32.008 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.008 r"""
2025-07-02 04:52:32.008 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.008 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.008 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.008 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.008
2025-07-02 04:52:32.008 Example:
2025-07-02 04:52:32.008
2025-07-02 04:52:32.008 >>> d = Differ()
2025-07-02 04:52:32.008 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.008 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.008 >>> print(''.join(results), end="")
2025-07-02 04:52:32.008 - abcDefghiJkl
2025-07-02 04:52:32.008 + abcdefGhijkl
2025-07-02 04:52:32.008 """
2025-07-02 04:52:32.008
2025-07-02 04:52:32.008 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.008 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.009 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.009 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.009 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.009
2025-07-02 04:52:32.009 # search for the pair that matches best without being identical
2025-07-02 04:52:32.009 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.009 # on junk -- unless we have to)
2025-07-02 04:52:32.009 for j in range(blo, bhi):
2025-07-02 04:52:32.009 bj = b[j]
2025-07-02 04:52:32.009 cruncher.set_seq2(bj)
2025-07-02 04:52:32.009 for i in range(alo, ahi):
2025-07-02 04:52:32.009 ai = a[i]
2025-07-02 04:52:32.009 if ai == bj:
2025-07-02 04:52:32.009 if eqi is None:
2025-07-02 04:52:32.009 eqi, eqj = i, j
2025-07-02 04:52:32.009 continue
2025-07-02 04:52:32.009 cruncher.set_seq1(ai)
2025-07-02 04:52:32.009 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.009 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.009 # compares by a factor of 3.
2025-07-02 04:52:32.009 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.010 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.010 # of the computation is cached by cruncher
2025-07-02 04:52:32.010 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.010 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.010 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.010 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.010 if best_ratio < cutoff:
2025-07-02 04:52:32.010 # no non-identical "pretty close" pair
2025-07-02 04:52:32.010 if eqi is None:
2025-07-02 04:52:32.010 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.010 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.010 return
2025-07-02 04:52:32.010 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.010 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.010 else:
2025-07-02 04:52:32.010 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.010 eqi = None
2025-07-02 04:52:32.010
2025-07-02 04:52:32.010 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.010 # identical
2025-07-02 04:52:32.011
2025-07-02 04:52:32.011 # pump out diffs from before the synch point
2025-07-02 04:52:32.011 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.011
2025-07-02 04:52:32.011 # do intraline marking on the synch pair
2025-07-02 04:52:32.011 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.011 if eqi is None:
2025-07-02 04:52:32.011 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.011 atags = btags = ""
2025-07-02 04:52:32.011 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.011 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.011 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.011 if tag == 'replace':
2025-07-02 04:52:32.011 atags += '^' * la
2025-07-02 04:52:32.011 btags += '^' * lb
2025-07-02 04:52:32.011 elif tag == 'delete':
2025-07-02 04:52:32.011 atags += '-' * la
2025-07-02 04:52:32.011 elif tag == 'insert':
2025-07-02 04:52:32.011 btags += '+' * lb
2025-07-02 04:52:32.011 elif tag == 'equal':
2025-07-02 04:52:32.011 atags += ' ' * la
2025-07-02 04:52:32.012 btags += ' ' * lb
2025-07-02 04:52:32.012 else:
2025-07-02 04:52:32.012 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.012 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.012 else:
2025-07-02 04:52:32.012 # the synch pair is identical
2025-07-02 04:52:32.012 yield ' ' + aelt
2025-07-02 04:52:32.012
2025-07-02 04:52:32.012 # pump out diffs from after the synch point
2025-07-02 04:52:32.012 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.012
2025-07-02 04:52:32.012 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.012 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.012
2025-07-02 04:52:32.012 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.012 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.012 alo = 148, ahi = 1101
2025-07-02 04:52:32.012 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.012 blo = 148, bhi = 1101
2025-07-02 04:52:32.012
2025-07-02 04:52:32.013 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.013 g = []
2025-07-02 04:52:32.013 if alo < ahi:
2025-07-02 04:52:32.013 if blo < bhi:
2025-07-02 04:52:32.013 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.013 else:
2025-07-02 04:52:32.013 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.013 elif blo < bhi:
2025-07-02 04:52:32.013 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.013
2025-07-02 04:52:32.013 > yield from g
2025-07-02 04:52:32.013
2025-07-02 04:52:32.013 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.013 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.013
2025-07-02 04:52:32.013 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.013 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.013 alo = 148, ahi = 1101
2025-07-02 04:52:32.013 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.013 blo = 148, bhi = 1101
2025-07-02 04:52:32.013
2025-07-02 04:52:32.014 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.014 r"""
2025-07-02 04:52:32.014 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.014 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.014 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.014 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.014
2025-07-02 04:52:32.014 Example:
2025-07-02 04:52:32.014
2025-07-02 04:52:32.014 >>> d = Differ()
2025-07-02 04:52:32.014 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.014 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.014 >>> print(''.join(results), end="")
2025-07-02 04:52:32.014 - abcDefghiJkl
2025-07-02 04:52:32.014 + abcdefGhijkl
2025-07-02 04:52:32.014 """
2025-07-02 04:52:32.014
2025-07-02 04:52:32.014 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.014 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.015 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.015 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.015 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.015
2025-07-02 04:52:32.015 # search for the pair that matches best without being identical
2025-07-02 04:52:32.015 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.015 # on junk -- unless we have to)
2025-07-02 04:52:32.015 for j in range(blo, bhi):
2025-07-02 04:52:32.015 bj = b[j]
2025-07-02 04:52:32.015 cruncher.set_seq2(bj)
2025-07-02 04:52:32.015 for i in range(alo, ahi):
2025-07-02 04:52:32.015 ai = a[i]
2025-07-02 04:52:32.015 if ai == bj:
2025-07-02 04:52:32.015 if eqi is None:
2025-07-02 04:52:32.015 eqi, eqj = i, j
2025-07-02 04:52:32.015 continue
2025-07-02 04:52:32.015 cruncher.set_seq1(ai)
2025-07-02 04:52:32.015 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.015 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.015 # compares by a factor of 3.
2025-07-02 04:52:32.015 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.015 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.016 # of the computation is cached by cruncher
2025-07-02 04:52:32.016 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.016 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.016 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.016 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.016 if best_ratio < cutoff:
2025-07-02 04:52:32.016 # no non-identical "pretty close" pair
2025-07-02 04:52:32.016 if eqi is None:
2025-07-02 04:52:32.016 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.016 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.016 return
2025-07-02 04:52:32.016 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.016 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.016 else:
2025-07-02 04:52:32.016 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.016 eqi = None
2025-07-02 04:52:32.016
2025-07-02 04:52:32.016 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.016 # identical
2025-07-02 04:52:32.016
2025-07-02 04:52:32.016 # pump out diffs from before the synch point
2025-07-02 04:52:32.017 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.017
2025-07-02 04:52:32.017 # do intraline marking on the synch pair
2025-07-02 04:52:32.017 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.017 if eqi is None:
2025-07-02 04:52:32.017 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.017 atags = btags = ""
2025-07-02 04:52:32.017 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.017 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.017 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.017 if tag == 'replace':
2025-07-02 04:52:32.017 atags += '^' * la
2025-07-02 04:52:32.017 btags += '^' * lb
2025-07-02 04:52:32.017 elif tag == 'delete':
2025-07-02 04:52:32.017 atags += '-' * la
2025-07-02 04:52:32.017 elif tag == 'insert':
2025-07-02 04:52:32.017 btags += '+' * lb
2025-07-02 04:52:32.017 elif tag == 'equal':
2025-07-02 04:52:32.017 atags += ' ' * la
2025-07-02 04:52:32.017 btags += ' ' * lb
2025-07-02 04:52:32.017 else:
2025-07-02 04:52:32.017 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.018 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.018 else:
2025-07-02 04:52:32.018 # the synch pair is identical
2025-07-02 04:52:32.018 yield ' ' + aelt
2025-07-02 04:52:32.018
2025-07-02 04:52:32.018 # pump out diffs from after the synch point
2025-07-02 04:52:32.018 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.018
2025-07-02 04:52:32.018 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.018 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.018
2025-07-02 04:52:32.018 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.018 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.018 alo = 149, ahi = 1101
2025-07-02 04:52:32.018 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.018 blo = 149, bhi = 1101
2025-07-02 04:52:32.018
2025-07-02 04:52:32.018 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.018 g = []
2025-07-02 04:52:32.019 if alo < ahi:
2025-07-02 04:52:32.019 if blo < bhi:
2025-07-02 04:52:32.019 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.019 else:
2025-07-02 04:52:32.019 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.019 elif blo < bhi:
2025-07-02 04:52:32.019 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.019
2025-07-02 04:52:32.019 > yield from g
2025-07-02 04:52:32.019
2025-07-02 04:52:32.019 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.019 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.019
2025-07-02 04:52:32.019 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.019 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.019 alo = 149, ahi = 1101
2025-07-02 04:52:32.019 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.019 blo = 149, bhi = 1101
2025-07-02 04:52:32.019
2025-07-02 04:52:32.019 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.019 r"""
2025-07-02 04:52:32.020 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.020 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.020 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.020 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.020
2025-07-02 04:52:32.020 Example:
2025-07-02 04:52:32.020
2025-07-02 04:52:32.020 >>> d = Differ()
2025-07-02 04:52:32.020 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.020 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.020 >>> print(''.join(results), end="")
2025-07-02 04:52:32.020 - abcDefghiJkl
2025-07-02 04:52:32.020 + abcdefGhijkl
2025-07-02 04:52:32.020 """
2025-07-02 04:52:32.020
2025-07-02 04:52:32.020 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.020 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.020 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.020 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.021 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.021
2025-07-02 04:52:32.021 # search for the pair that matches best without being identical
2025-07-02 04:52:32.021 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.021 # on junk -- unless we have to)
2025-07-02 04:52:32.021 for j in range(blo, bhi):
2025-07-02 04:52:32.021 bj = b[j]
2025-07-02 04:52:32.021 cruncher.set_seq2(bj)
2025-07-02 04:52:32.021 for i in range(alo, ahi):
2025-07-02 04:52:32.021 ai = a[i]
2025-07-02 04:52:32.021 if ai == bj:
2025-07-02 04:52:32.021 if eqi is None:
2025-07-02 04:52:32.021 eqi, eqj = i, j
2025-07-02 04:52:32.021 continue
2025-07-02 04:52:32.021 cruncher.set_seq1(ai)
2025-07-02 04:52:32.021 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.021 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.021 # compares by a factor of 3.
2025-07-02 04:52:32.021 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.021 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.021 # of the computation is cached by cruncher
2025-07-02 04:52:32.022 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.022 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.022 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.022 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.022 if best_ratio < cutoff:
2025-07-02 04:52:32.022 # no non-identical "pretty close" pair
2025-07-02 04:52:32.022 if eqi is None:
2025-07-02 04:52:32.022 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.022 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.022 return
2025-07-02 04:52:32.022 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.022 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.022 else:
2025-07-02 04:52:32.022 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.022 eqi = None
2025-07-02 04:52:32.022
2025-07-02 04:52:32.022 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.022 # identical
2025-07-02 04:52:32.022
2025-07-02 04:52:32.022 # pump out diffs from before the synch point
2025-07-02 04:52:32.022 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.023
2025-07-02 04:52:32.023 # do intraline marking on the synch pair
2025-07-02 04:52:32.023 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.023 if eqi is None:
2025-07-02 04:52:32.023 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.023 atags = btags = ""
2025-07-02 04:52:32.023 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.023 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.023 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.023 if tag == 'replace':
2025-07-02 04:52:32.023 atags += '^' * la
2025-07-02 04:52:32.023 btags += '^' * lb
2025-07-02 04:52:32.023 elif tag == 'delete':
2025-07-02 04:52:32.023 atags += '-' * la
2025-07-02 04:52:32.023 elif tag == 'insert':
2025-07-02 04:52:32.023 btags += '+' * lb
2025-07-02 04:52:32.023 elif tag == 'equal':
2025-07-02 04:52:32.023 atags += ' ' * la
2025-07-02 04:52:32.023 btags += ' ' * lb
2025-07-02 04:52:32.023 else:
2025-07-02 04:52:32.023 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.024 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.024 else:
2025-07-02 04:52:32.024 # the synch pair is identical
2025-07-02 04:52:32.024 yield ' ' + aelt
2025-07-02 04:52:32.024
2025-07-02 04:52:32.024 # pump out diffs from after the synch point
2025-07-02 04:52:32.024 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.024
2025-07-02 04:52:32.024 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.024 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.024
2025-07-02 04:52:32.024 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.024 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.024 alo = 150, ahi = 1101
2025-07-02 04:52:32.024 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.024 blo = 150, bhi = 1101
2025-07-02 04:52:32.024
2025-07-02 04:52:32.024 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.024 g = []
2025-07-02 04:52:32.024 if alo < ahi:
2025-07-02 04:52:32.024 if blo < bhi:
2025-07-02 04:52:32.025 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.025 else:
2025-07-02 04:52:32.025 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.025 elif blo < bhi:
2025-07-02 04:52:32.025 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.025
2025-07-02 04:52:32.025 > yield from g
2025-07-02 04:52:32.025
2025-07-02 04:52:32.025 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.025 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.025
2025-07-02 04:52:32.025 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.025 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.025 alo = 150, ahi = 1101
2025-07-02 04:52:32.025 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.025 blo = 150, bhi = 1101
2025-07-02 04:52:32.025
2025-07-02 04:52:32.025 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.025 r"""
2025-07-02 04:52:32.025 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.025 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.026 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.026 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.026
2025-07-02 04:52:32.026 Example:
2025-07-02 04:52:32.026
2025-07-02 04:52:32.026 >>> d = Differ()
2025-07-02 04:52:32.026 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.026 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.026 >>> print(''.join(results), end="")
2025-07-02 04:52:32.026 - abcDefghiJkl
2025-07-02 04:52:32.026 + abcdefGhijkl
2025-07-02 04:52:32.026 """
2025-07-02 04:52:32.026
2025-07-02 04:52:32.026 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.026 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.026 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.026 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.026 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.027
2025-07-02 04:52:32.027 # search for the pair that matches best without being identical
2025-07-02 04:52:32.027 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.027 # on junk -- unless we have to)
2025-07-02 04:52:32.027 for j in range(blo, bhi):
2025-07-02 04:52:32.027 bj = b[j]
2025-07-02 04:52:32.027 cruncher.set_seq2(bj)
2025-07-02 04:52:32.027 for i in range(alo, ahi):
2025-07-02 04:52:32.027 ai = a[i]
2025-07-02 04:52:32.027 if ai == bj:
2025-07-02 04:52:32.027 if eqi is None:
2025-07-02 04:52:32.027 eqi, eqj = i, j
2025-07-02 04:52:32.027 continue
2025-07-02 04:52:32.027 cruncher.set_seq1(ai)
2025-07-02 04:52:32.027 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.027 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.027 # compares by a factor of 3.
2025-07-02 04:52:32.027 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.027 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.027 # of the computation is cached by cruncher
2025-07-02 04:52:32.027 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.028 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.028 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.028 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.028 if best_ratio < cutoff:
2025-07-02 04:52:32.028 # no non-identical "pretty close" pair
2025-07-02 04:52:32.028 if eqi is None:
2025-07-02 04:52:32.028 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.028 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.028 return
2025-07-02 04:52:32.028 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.028 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.028 else:
2025-07-02 04:52:32.028 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.028 eqi = None
2025-07-02 04:52:32.028
2025-07-02 04:52:32.028 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.028 # identical
2025-07-02 04:52:32.028
2025-07-02 04:52:32.028 # pump out diffs from before the synch point
2025-07-02 04:52:32.028 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.028
2025-07-02 04:52:32.029 # do intraline marking on the synch pair
2025-07-02 04:52:32.029 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.029 if eqi is None:
2025-07-02 04:52:32.029 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.029 atags = btags = ""
2025-07-02 04:52:32.029 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.029 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.029 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.029 if tag == 'replace':
2025-07-02 04:52:32.029 atags += '^' * la
2025-07-02 04:52:32.029 btags += '^' * lb
2025-07-02 04:52:32.029 elif tag == 'delete':
2025-07-02 04:52:32.029 atags += '-' * la
2025-07-02 04:52:32.029 elif tag == 'insert':
2025-07-02 04:52:32.029 btags += '+' * lb
2025-07-02 04:52:32.029 elif tag == 'equal':
2025-07-02 04:52:32.029 atags += ' ' * la
2025-07-02 04:52:32.029 btags += ' ' * lb
2025-07-02 04:52:32.029 else:
2025-07-02 04:52:32.029 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.029 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.030 else:
2025-07-02 04:52:32.030 # the synch pair is identical
2025-07-02 04:52:32.030 yield ' ' + aelt
2025-07-02 04:52:32.030
2025-07-02 04:52:32.030 # pump out diffs from after the synch point
2025-07-02 04:52:32.030 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.030
2025-07-02 04:52:32.030 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.030 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.030
2025-07-02 04:52:32.030 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.030 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.030 alo = 151, ahi = 1101
2025-07-02 04:52:32.030 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.030 blo = 151, bhi = 1101
2025-07-02 04:52:32.030
2025-07-02 04:52:32.030 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.030 g = []
2025-07-02 04:52:32.030 if alo < ahi:
2025-07-02 04:52:32.030 if blo < bhi:
2025-07-02 04:52:32.030 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.031 else:
2025-07-02 04:52:32.031 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.031 elif blo < bhi:
2025-07-02 04:52:32.031 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.031
2025-07-02 04:52:32.031 > yield from g
2025-07-02 04:52:32.031
2025-07-02 04:52:32.031 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.031 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.031
2025-07-02 04:52:32.031 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.031 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.031 alo = 151, ahi = 1101
2025-07-02 04:52:32.031 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.031 blo = 151, bhi = 1101
2025-07-02 04:52:32.031
2025-07-02 04:52:32.031 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.031 r"""
2025-07-02 04:52:32.031 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.031 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.031 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.031 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.032
2025-07-02 04:52:32.032 Example:
2025-07-02 04:52:32.032
2025-07-02 04:52:32.032 >>> d = Differ()
2025-07-02 04:52:32.032 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.032 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.032 >>> print(''.join(results), end="")
2025-07-02 04:52:32.032 - abcDefghiJkl
2025-07-02 04:52:32.032 + abcdefGhijkl
2025-07-02 04:52:32.032 """
2025-07-02 04:52:32.032
2025-07-02 04:52:32.032 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.032 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.032 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.032 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.032 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.032
2025-07-02 04:52:32.032 # search for the pair that matches best without being identical
2025-07-02 04:52:32.032 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.033 # on junk -- unless we have to)
2025-07-02 04:52:32.033 for j in range(blo, bhi):
2025-07-02 04:52:32.033 bj = b[j]
2025-07-02 04:52:32.033 cruncher.set_seq2(bj)
2025-07-02 04:52:32.033 for i in range(alo, ahi):
2025-07-02 04:52:32.033 ai = a[i]
2025-07-02 04:52:32.033 if ai == bj:
2025-07-02 04:52:32.033 if eqi is None:
2025-07-02 04:52:32.033 eqi, eqj = i, j
2025-07-02 04:52:32.033 continue
2025-07-02 04:52:32.033 cruncher.set_seq1(ai)
2025-07-02 04:52:32.033 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.033 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.033 # compares by a factor of 3.
2025-07-02 04:52:32.033 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.033 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.033 # of the computation is cached by cruncher
2025-07-02 04:52:32.033 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.033 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.033 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.033 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.034 if best_ratio < cutoff:
2025-07-02 04:52:32.034 # no non-identical "pretty close" pair
2025-07-02 04:52:32.034 if eqi is None:
2025-07-02 04:52:32.034 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.034 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.034 return
2025-07-02 04:52:32.034 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.034 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.034 else:
2025-07-02 04:52:32.034 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.034 eqi = None
2025-07-02 04:52:32.034
2025-07-02 04:52:32.034 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.034 # identical
2025-07-02 04:52:32.034
2025-07-02 04:52:32.034 # pump out diffs from before the synch point
2025-07-02 04:52:32.034 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.034
2025-07-02 04:52:32.034 # do intraline marking on the synch pair
2025-07-02 04:52:32.034 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.034 if eqi is None:
2025-07-02 04:52:32.035 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.035 atags = btags = ""
2025-07-02 04:52:32.035 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.035 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.035 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.035 if tag == 'replace':
2025-07-02 04:52:32.035 atags += '^' * la
2025-07-02 04:52:32.035 btags += '^' * lb
2025-07-02 04:52:32.035 elif tag == 'delete':
2025-07-02 04:52:32.035 atags += '-' * la
2025-07-02 04:52:32.035 elif tag == 'insert':
2025-07-02 04:52:32.035 btags += '+' * lb
2025-07-02 04:52:32.035 elif tag == 'equal':
2025-07-02 04:52:32.035 atags += ' ' * la
2025-07-02 04:52:32.035 btags += ' ' * lb
2025-07-02 04:52:32.035 else:
2025-07-02 04:52:32.035 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.035 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.035 else:
2025-07-02 04:52:32.035 # the synch pair is identical
2025-07-02 04:52:32.036 yield ' ' + aelt
2025-07-02 04:52:32.036
2025-07-02 04:52:32.036 # pump out diffs from after the synch point
2025-07-02 04:52:32.036 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.036
2025-07-02 04:52:32.036 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.036 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.036
2025-07-02 04:52:32.036 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.036 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.036 alo = 152, ahi = 1101
2025-07-02 04:52:32.036 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.036 blo = 152, bhi = 1101
2025-07-02 04:52:32.036
2025-07-02 04:52:32.036 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.036 g = []
2025-07-02 04:52:32.036 if alo < ahi:
2025-07-02 04:52:32.036 if blo < bhi:
2025-07-02 04:52:32.036 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.036 else:
2025-07-02 04:52:32.037 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.037 elif blo < bhi:
2025-07-02 04:52:32.037 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.037
2025-07-02 04:52:32.037 > yield from g
2025-07-02 04:52:32.037
2025-07-02 04:52:32.037 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.037 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.037
2025-07-02 04:52:32.037 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.037 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.037 alo = 152, ahi = 1101
2025-07-02 04:52:32.037 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.037 blo = 152, bhi = 1101
2025-07-02 04:52:32.037
2025-07-02 04:52:32.037 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.037 r"""
2025-07-02 04:52:32.037 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.037 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.037 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.037 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.037
2025-07-02 04:52:32.038 Example:
2025-07-02 04:52:32.038
2025-07-02 04:52:32.038 >>> d = Differ()
2025-07-02 04:52:32.038 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.038 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.038 >>> print(''.join(results), end="")
2025-07-02 04:52:32.038 - abcDefghiJkl
2025-07-02 04:52:32.038 + abcdefGhijkl
2025-07-02 04:52:32.038 """
2025-07-02 04:52:32.038
2025-07-02 04:52:32.038 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.038 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.038 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.038 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.038 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.038
2025-07-02 04:52:32.038 # search for the pair that matches best without being identical
2025-07-02 04:52:32.038 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.038 # on junk -- unless we have to)
2025-07-02 04:52:32.039 for j in range(blo, bhi):
2025-07-02 04:52:32.039 bj = b[j]
2025-07-02 04:52:32.039 cruncher.set_seq2(bj)
2025-07-02 04:52:32.039 for i in range(alo, ahi):
2025-07-02 04:52:32.039 ai = a[i]
2025-07-02 04:52:32.039 if ai == bj:
2025-07-02 04:52:32.039 if eqi is None:
2025-07-02 04:52:32.039 eqi, eqj = i, j
2025-07-02 04:52:32.039 continue
2025-07-02 04:52:32.039 cruncher.set_seq1(ai)
2025-07-02 04:52:32.039 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.039 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.039 # compares by a factor of 3.
2025-07-02 04:52:32.039 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.039 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.039 # of the computation is cached by cruncher
2025-07-02 04:52:32.039 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.039 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.039 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.039 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.040 if best_ratio < cutoff:
2025-07-02 04:52:32.040 # no non-identical "pretty close" pair
2025-07-02 04:52:32.040 if eqi is None:
2025-07-02 04:52:32.040 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.040 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.040 return
2025-07-02 04:52:32.040 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.040 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.040 else:
2025-07-02 04:52:32.040 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.040 eqi = None
2025-07-02 04:52:32.040
2025-07-02 04:52:32.040 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.040 # identical
2025-07-02 04:52:32.040
2025-07-02 04:52:32.040 # pump out diffs from before the synch point
2025-07-02 04:52:32.040 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.040
2025-07-02 04:52:32.040 # do intraline marking on the synch pair
2025-07-02 04:52:32.040 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.040 if eqi is None:
2025-07-02 04:52:32.041 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.041 atags = btags = ""
2025-07-02 04:52:32.041 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.041 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.041 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.041 if tag == 'replace':
2025-07-02 04:52:32.041 atags += '^' * la
2025-07-02 04:52:32.041 btags += '^' * lb
2025-07-02 04:52:32.041 elif tag == 'delete':
2025-07-02 04:52:32.041 atags += '-' * la
2025-07-02 04:52:32.041 elif tag == 'insert':
2025-07-02 04:52:32.041 btags += '+' * lb
2025-07-02 04:52:32.041 elif tag == 'equal':
2025-07-02 04:52:32.041 atags += ' ' * la
2025-07-02 04:52:32.041 btags += ' ' * lb
2025-07-02 04:52:32.041 else:
2025-07-02 04:52:32.041 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.041 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.041 else:
2025-07-02 04:52:32.041 # the synch pair is identical
2025-07-02 04:52:32.041 yield ' ' + aelt
2025-07-02 04:52:32.042
2025-07-02 04:52:32.042 # pump out diffs from after the synch point
2025-07-02 04:52:32.042 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.042
2025-07-02 04:52:32.042 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.042 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.042
2025-07-02 04:52:32.042 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.042 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.042 alo = 153, ahi = 1101
2025-07-02 04:52:32.042 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.042 blo = 153, bhi = 1101
2025-07-02 04:52:32.042
2025-07-02 04:52:32.042 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.042 g = []
2025-07-02 04:52:32.042 if alo < ahi:
2025-07-02 04:52:32.042 if blo < bhi:
2025-07-02 04:52:32.042 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.042 else:
2025-07-02 04:52:32.043 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.043 elif blo < bhi:
2025-07-02 04:52:32.043 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.043
2025-07-02 04:52:32.043 > yield from g
2025-07-02 04:52:32.043
2025-07-02 04:52:32.043 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.043 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.043
2025-07-02 04:52:32.043 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.043 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.043 alo = 153, ahi = 1101
2025-07-02 04:52:32.043 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.043 blo = 153, bhi = 1101
2025-07-02 04:52:32.043
2025-07-02 04:52:32.043 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.043 r"""
2025-07-02 04:52:32.043 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.043 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.043 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.044 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.044
2025-07-02 04:52:32.044 Example:
2025-07-02 04:52:32.044
2025-07-02 04:52:32.044 >>> d = Differ()
2025-07-02 04:52:32.044 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.044 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.044 >>> print(''.join(results), end="")
2025-07-02 04:52:32.044 - abcDefghiJkl
2025-07-02 04:52:32.044 + abcdefGhijkl
2025-07-02 04:52:32.044 """
2025-07-02 04:52:32.044
2025-07-02 04:52:32.044 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.044 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.044 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.044 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.044 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.045
2025-07-02 04:52:32.045 # search for the pair that matches best without being identical
2025-07-02 04:52:32.045 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.045 # on junk -- unless we have to)
2025-07-02 04:52:32.045 for j in range(blo, bhi):
2025-07-02 04:52:32.045 bj = b[j]
2025-07-02 04:52:32.045 cruncher.set_seq2(bj)
2025-07-02 04:52:32.045 for i in range(alo, ahi):
2025-07-02 04:52:32.045 ai = a[i]
2025-07-02 04:52:32.045 if ai == bj:
2025-07-02 04:52:32.045 if eqi is None:
2025-07-02 04:52:32.045 eqi, eqj = i, j
2025-07-02 04:52:32.045 continue
2025-07-02 04:52:32.045 cruncher.set_seq1(ai)
2025-07-02 04:52:32.045 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.045 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.045 # compares by a factor of 3.
2025-07-02 04:52:32.045 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.045 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.045 # of the computation is cached by cruncher
2025-07-02 04:52:32.045 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.046 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.046 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.046 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.046 if best_ratio < cutoff:
2025-07-02 04:52:32.046 # no non-identical "pretty close" pair
2025-07-02 04:52:32.046 if eqi is None:
2025-07-02 04:52:32.046 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.046 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.046 return
2025-07-02 04:52:32.046 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.046 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.046 else:
2025-07-02 04:52:32.046 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.046 eqi = None
2025-07-02 04:52:32.046
2025-07-02 04:52:32.046 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.046 # identical
2025-07-02 04:52:32.046
2025-07-02 04:52:32.046 # pump out diffs from before the synch point
2025-07-02 04:52:32.046 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.046
2025-07-02 04:52:32.047 # do intraline marking on the synch pair
2025-07-02 04:52:32.047 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.047 if eqi is None:
2025-07-02 04:52:32.047 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.047 atags = btags = ""
2025-07-02 04:52:32.047 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.047 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.047 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.047 if tag == 'replace':
2025-07-02 04:52:32.047 atags += '^' * la
2025-07-02 04:52:32.047 btags += '^' * lb
2025-07-02 04:52:32.047 elif tag == 'delete':
2025-07-02 04:52:32.047 atags += '-' * la
2025-07-02 04:52:32.047 elif tag == 'insert':
2025-07-02 04:52:32.047 btags += '+' * lb
2025-07-02 04:52:32.047 elif tag == 'equal':
2025-07-02 04:52:32.047 atags += ' ' * la
2025-07-02 04:52:32.047 btags += ' ' * lb
2025-07-02 04:52:32.047 else:
2025-07-02 04:52:32.047 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.047 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.047 else:
2025-07-02 04:52:32.048 # the synch pair is identical
2025-07-02 04:52:32.048 yield ' ' + aelt
2025-07-02 04:52:32.048
2025-07-02 04:52:32.048 # pump out diffs from after the synch point
2025-07-02 04:52:32.048 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.048
2025-07-02 04:52:32.048 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.048 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.048
2025-07-02 04:52:32.048 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.048 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.048 alo = 154, ahi = 1101
2025-07-02 04:52:32.048 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.048 blo = 154, bhi = 1101
2025-07-02 04:52:32.048
2025-07-02 04:52:32.048 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.048 g = []
2025-07-02 04:52:32.048 if alo < ahi:
2025-07-02 04:52:32.048 if blo < bhi:
2025-07-02 04:52:32.048 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.048 else:
2025-07-02 04:52:32.049 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.049 elif blo < bhi:
2025-07-02 04:52:32.049 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.049
2025-07-02 04:52:32.049 > yield from g
2025-07-02 04:52:32.049
2025-07-02 04:52:32.049 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.049 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.049
2025-07-02 04:52:32.049 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.049 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.049 alo = 154, ahi = 1101
2025-07-02 04:52:32.049 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.049 blo = 154, bhi = 1101
2025-07-02 04:52:32.049
2025-07-02 04:52:32.049 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.049 r"""
2025-07-02 04:52:32.049 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.049 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.049 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.049 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.050
2025-07-02 04:52:32.050 Example:
2025-07-02 04:52:32.050
2025-07-02 04:52:32.050 >>> d = Differ()
2025-07-02 04:52:32.050 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.050 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.050 >>> print(''.join(results), end="")
2025-07-02 04:52:32.050 - abcDefghiJkl
2025-07-02 04:52:32.050 + abcdefGhijkl
2025-07-02 04:52:32.050 """
2025-07-02 04:52:32.050
2025-07-02 04:52:32.050 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.050 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.050 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.050 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.050 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.050
2025-07-02 04:52:32.050 # search for the pair that matches best without being identical
2025-07-02 04:52:32.050 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.051 # on junk -- unless we have to)
2025-07-02 04:52:32.051 for j in range(blo, bhi):
2025-07-02 04:52:32.051 bj = b[j]
2025-07-02 04:52:32.051 cruncher.set_seq2(bj)
2025-07-02 04:52:32.051 for i in range(alo, ahi):
2025-07-02 04:52:32.051 ai = a[i]
2025-07-02 04:52:32.051 if ai == bj:
2025-07-02 04:52:32.051 if eqi is None:
2025-07-02 04:52:32.051 eqi, eqj = i, j
2025-07-02 04:52:32.051 continue
2025-07-02 04:52:32.051 cruncher.set_seq1(ai)
2025-07-02 04:52:32.051 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.051 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.051 # compares by a factor of 3.
2025-07-02 04:52:32.051 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.051 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.051 # of the computation is cached by cruncher
2025-07-02 04:52:32.051 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.051 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.051 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.052 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.052 if best_ratio < cutoff:
2025-07-02 04:52:32.052 # no non-identical "pretty close" pair
2025-07-02 04:52:32.052 if eqi is None:
2025-07-02 04:52:32.052 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.052 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.052 return
2025-07-02 04:52:32.052 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.052 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.052 else:
2025-07-02 04:52:32.052 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.052 eqi = None
2025-07-02 04:52:32.052
2025-07-02 04:52:32.052 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.052 # identical
2025-07-02 04:52:32.052
2025-07-02 04:52:32.052 # pump out diffs from before the synch point
2025-07-02 04:52:32.052 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.052
2025-07-02 04:52:32.052 # do intraline marking on the synch pair
2025-07-02 04:52:32.052 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.053 if eqi is None:
2025-07-02 04:52:32.053 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.053 atags = btags = ""
2025-07-02 04:52:32.053 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.053 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.053 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.053 if tag == 'replace':
2025-07-02 04:52:32.053 atags += '^' * la
2025-07-02 04:52:32.053 btags += '^' * lb
2025-07-02 04:52:32.053 elif tag == 'delete':
2025-07-02 04:52:32.053 atags += '-' * la
2025-07-02 04:52:32.053 elif tag == 'insert':
2025-07-02 04:52:32.053 btags += '+' * lb
2025-07-02 04:52:32.053 elif tag == 'equal':
2025-07-02 04:52:32.053 atags += ' ' * la
2025-07-02 04:52:32.053 btags += ' ' * lb
2025-07-02 04:52:32.053 else:
2025-07-02 04:52:32.053 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.053 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.053 else:
2025-07-02 04:52:32.053 # the synch pair is identical
2025-07-02 04:52:32.054 yield ' ' + aelt
2025-07-02 04:52:32.054
2025-07-02 04:52:32.054 # pump out diffs from after the synch point
2025-07-02 04:52:32.054 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.054
2025-07-02 04:52:32.054 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.054 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.054
2025-07-02 04:52:32.054 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.054 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.054 alo = 155, ahi = 1101
2025-07-02 04:52:32.054 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.054 blo = 155, bhi = 1101
2025-07-02 04:52:32.054
2025-07-02 04:52:32.054 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.054 g = []
2025-07-02 04:52:32.054 if alo < ahi:
2025-07-02 04:52:32.054 if blo < bhi:
2025-07-02 04:52:32.054 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.054 else:
2025-07-02 04:52:32.054 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.055 elif blo < bhi:
2025-07-02 04:52:32.055 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.055
2025-07-02 04:52:32.055 > yield from g
2025-07-02 04:52:32.055
2025-07-02 04:52:32.055 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.055 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.055
2025-07-02 04:52:32.055 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.055 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.055 alo = 155, ahi = 1101
2025-07-02 04:52:32.055 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.055 blo = 155, bhi = 1101
2025-07-02 04:52:32.055
2025-07-02 04:52:32.055 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.055 r"""
2025-07-02 04:52:32.055 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.055 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.055 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.055 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.056
2025-07-02 04:52:32.056 Example:
2025-07-02 04:52:32.056
2025-07-02 04:52:32.056 >>> d = Differ()
2025-07-02 04:52:32.056 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.056 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.056 >>> print(''.join(results), end="")
2025-07-02 04:52:32.056 - abcDefghiJkl
2025-07-02 04:52:32.056 + abcdefGhijkl
2025-07-02 04:52:32.056 """
2025-07-02 04:52:32.056
2025-07-02 04:52:32.056 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.056 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.056 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.056 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.056 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.056
2025-07-02 04:52:32.056 # search for the pair that matches best without being identical
2025-07-02 04:52:32.056 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.057 # on junk -- unless we have to)
2025-07-02 04:52:32.057 for j in range(blo, bhi):
2025-07-02 04:52:32.057 bj = b[j]
2025-07-02 04:52:32.057 cruncher.set_seq2(bj)
2025-07-02 04:52:32.057 for i in range(alo, ahi):
2025-07-02 04:52:32.057 ai = a[i]
2025-07-02 04:52:32.057 if ai == bj:
2025-07-02 04:52:32.057 if eqi is None:
2025-07-02 04:52:32.057 eqi, eqj = i, j
2025-07-02 04:52:32.057 continue
2025-07-02 04:52:32.057 cruncher.set_seq1(ai)
2025-07-02 04:52:32.057 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.057 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.057 # compares by a factor of 3.
2025-07-02 04:52:32.057 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.057 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.057 # of the computation is cached by cruncher
2025-07-02 04:52:32.057 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.057 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.057 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.057 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.058 if best_ratio < cutoff:
2025-07-02 04:52:32.058 # no non-identical "pretty close" pair
2025-07-02 04:52:32.058 if eqi is None:
2025-07-02 04:52:32.058 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.058 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.058 return
2025-07-02 04:52:32.058 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.058 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.058 else:
2025-07-02 04:52:32.058 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.058 eqi = None
2025-07-02 04:52:32.058
2025-07-02 04:52:32.058 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.058 # identical
2025-07-02 04:52:32.058
2025-07-02 04:52:32.058 # pump out diffs from before the synch point
2025-07-02 04:52:32.058 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.058
2025-07-02 04:52:32.058 # do intraline marking on the synch pair
2025-07-02 04:52:32.058 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.058 if eqi is None:
2025-07-02 04:52:32.058 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.059 atags = btags = ""
2025-07-02 04:52:32.059 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.059 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.059 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.059 if tag == 'replace':
2025-07-02 04:52:32.059 atags += '^' * la
2025-07-02 04:52:32.059 btags += '^' * lb
2025-07-02 04:52:32.059 elif tag == 'delete':
2025-07-02 04:52:32.059 atags += '-' * la
2025-07-02 04:52:32.059 elif tag == 'insert':
2025-07-02 04:52:32.059 btags += '+' * lb
2025-07-02 04:52:32.059 elif tag == 'equal':
2025-07-02 04:52:32.059 atags += ' ' * la
2025-07-02 04:52:32.059 btags += ' ' * lb
2025-07-02 04:52:32.059 else:
2025-07-02 04:52:32.059 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.059 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.059 else:
2025-07-02 04:52:32.059 # the synch pair is identical
2025-07-02 04:52:32.059 yield ' ' + aelt
2025-07-02 04:52:32.060
2025-07-02 04:52:32.060 # pump out diffs from after the synch point
2025-07-02 04:52:32.060 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.060
2025-07-02 04:52:32.060 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.060 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.060
2025-07-02 04:52:32.060 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.060 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.060 alo = 158, ahi = 1101
2025-07-02 04:52:32.060 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.060 blo = 158, bhi = 1101
2025-07-02 04:52:32.060
2025-07-02 04:52:32.060 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.060 g = []
2025-07-02 04:52:32.060 if alo < ahi:
2025-07-02 04:52:32.060 if blo < bhi:
2025-07-02 04:52:32.060 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.060 else:
2025-07-02 04:52:32.060 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.060 elif blo < bhi:
2025-07-02 04:52:32.061 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.061
2025-07-02 04:52:32.061 > yield from g
2025-07-02 04:52:32.061
2025-07-02 04:52:32.061 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.061 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.061
2025-07-02 04:52:32.061 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.061 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.061 alo = 158, ahi = 1101
2025-07-02 04:52:32.061 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.061 blo = 158, bhi = 1101
2025-07-02 04:52:32.061
2025-07-02 04:52:32.061 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.061 r"""
2025-07-02 04:52:32.061 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.061 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.061 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.061 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.061
2025-07-02 04:52:32.061 Example:
2025-07-02 04:52:32.062
2025-07-02 04:52:32.062 >>> d = Differ()
2025-07-02 04:52:32.062 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.062 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.062 >>> print(''.join(results), end="")
2025-07-02 04:52:32.062 - abcDefghiJkl
2025-07-02 04:52:32.062 + abcdefGhijkl
2025-07-02 04:52:32.062 """
2025-07-02 04:52:32.062
2025-07-02 04:52:32.062 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.062 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.062 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.062 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.062 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.062
2025-07-02 04:52:32.062 # search for the pair that matches best without being identical
2025-07-02 04:52:32.062 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.062 # on junk -- unless we have to)
2025-07-02 04:52:32.062 for j in range(blo, bhi):
2025-07-02 04:52:32.063 bj = b[j]
2025-07-02 04:52:32.063 cruncher.set_seq2(bj)
2025-07-02 04:52:32.063 for i in range(alo, ahi):
2025-07-02 04:52:32.063 ai = a[i]
2025-07-02 04:52:32.063 if ai == bj:
2025-07-02 04:52:32.063 if eqi is None:
2025-07-02 04:52:32.063 eqi, eqj = i, j
2025-07-02 04:52:32.063 continue
2025-07-02 04:52:32.063 cruncher.set_seq1(ai)
2025-07-02 04:52:32.063 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.063 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.063 # compares by a factor of 3.
2025-07-02 04:52:32.063 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.063 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.063 # of the computation is cached by cruncher
2025-07-02 04:52:32.063 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.063 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.063 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.063 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.063 if best_ratio < cutoff:
2025-07-02 04:52:32.063 # no non-identical "pretty close" pair
2025-07-02 04:52:32.064 if eqi is None:
2025-07-02 04:52:32.064 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.064 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.064 return
2025-07-02 04:52:32.064 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.064 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.064 else:
2025-07-02 04:52:32.064 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.064 eqi = None
2025-07-02 04:52:32.064
2025-07-02 04:52:32.064 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.064 # identical
2025-07-02 04:52:32.064
2025-07-02 04:52:32.064 # pump out diffs from before the synch point
2025-07-02 04:52:32.064 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.064
2025-07-02 04:52:32.064 # do intraline marking on the synch pair
2025-07-02 04:52:32.064 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.064 if eqi is None:
2025-07-02 04:52:32.064 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.064 atags = btags = ""
2025-07-02 04:52:32.064 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.065 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.065 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.065 if tag == 'replace':
2025-07-02 04:52:32.065 atags += '^' * la
2025-07-02 04:52:32.065 btags += '^' * lb
2025-07-02 04:52:32.065 elif tag == 'delete':
2025-07-02 04:52:32.065 atags += '-' * la
2025-07-02 04:52:32.065 elif tag == 'insert':
2025-07-02 04:52:32.065 btags += '+' * lb
2025-07-02 04:52:32.065 elif tag == 'equal':
2025-07-02 04:52:32.065 atags += ' ' * la
2025-07-02 04:52:32.065 btags += ' ' * lb
2025-07-02 04:52:32.065 else:
2025-07-02 04:52:32.065 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.065 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.065 else:
2025-07-02 04:52:32.065 # the synch pair is identical
2025-07-02 04:52:32.065 yield ' ' + aelt
2025-07-02 04:52:32.065
2025-07-02 04:52:32.066 # pump out diffs from after the synch point
2025-07-02 04:52:32.066 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.066
2025-07-02 04:52:32.066 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.066 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.066
2025-07-02 04:52:32.066 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.066 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.066 alo = 159, ahi = 1101
2025-07-02 04:52:32.066 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.066 blo = 159, bhi = 1101
2025-07-02 04:52:32.066
2025-07-02 04:52:32.066 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.066 g = []
2025-07-02 04:52:32.066 if alo < ahi:
2025-07-02 04:52:32.066 if blo < bhi:
2025-07-02 04:52:32.066 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.066 else:
2025-07-02 04:52:32.066 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.066 elif blo < bhi:
2025-07-02 04:52:32.066 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.067
2025-07-02 04:52:32.067 > yield from g
2025-07-02 04:52:32.067
2025-07-02 04:52:32.067 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.067 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.067
2025-07-02 04:52:32.067 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.067 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.067 alo = 159, ahi = 1101
2025-07-02 04:52:32.067 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.067 blo = 159, bhi = 1101
2025-07-02 04:52:32.067
2025-07-02 04:52:32.067 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.067 r"""
2025-07-02 04:52:32.067 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.067 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.067 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.067 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.067
2025-07-02 04:52:32.068 Example:
2025-07-02 04:52:32.068
2025-07-02 04:52:32.068 >>> d = Differ()
2025-07-02 04:52:32.068 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.068 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.068 >>> print(''.join(results), end="")
2025-07-02 04:52:32.068 - abcDefghiJkl
2025-07-02 04:52:32.068 + abcdefGhijkl
2025-07-02 04:52:32.068 """
2025-07-02 04:52:32.068
2025-07-02 04:52:32.068 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.068 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.068 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.068 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.068 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.068
2025-07-02 04:52:32.068 # search for the pair that matches best without being identical
2025-07-02 04:52:32.068 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.069 # on junk -- unless we have to)
2025-07-02 04:52:32.069 for j in range(blo, bhi):
2025-07-02 04:52:32.069 bj = b[j]
2025-07-02 04:52:32.069 cruncher.set_seq2(bj)
2025-07-02 04:52:32.069 for i in range(alo, ahi):
2025-07-02 04:52:32.069 ai = a[i]
2025-07-02 04:52:32.069 if ai == bj:
2025-07-02 04:52:32.069 if eqi is None:
2025-07-02 04:52:32.069 eqi, eqj = i, j
2025-07-02 04:52:32.069 continue
2025-07-02 04:52:32.069 cruncher.set_seq1(ai)
2025-07-02 04:52:32.069 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.069 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.069 # compares by a factor of 3.
2025-07-02 04:52:32.069 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.069 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.069 # of the computation is cached by cruncher
2025-07-02 04:52:32.069 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.069 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.070 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.070 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.070 if best_ratio < cutoff:
2025-07-02 04:52:32.070 # no non-identical "pretty close" pair
2025-07-02 04:52:32.070 if eqi is None:
2025-07-02 04:52:32.070 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.070 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.070 return
2025-07-02 04:52:32.070 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.070 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.070 else:
2025-07-02 04:52:32.070 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.070 eqi = None
2025-07-02 04:52:32.070
2025-07-02 04:52:32.070 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.070 # identical
2025-07-02 04:52:32.070
2025-07-02 04:52:32.070 # pump out diffs from before the synch point
2025-07-02 04:52:32.070 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.071
2025-07-02 04:52:32.071 # do intraline marking on the synch pair
2025-07-02 04:52:32.071 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.071 if eqi is None:
2025-07-02 04:52:32.071 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.071 atags = btags = ""
2025-07-02 04:52:32.071 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.071 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.071 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.071 if tag == 'replace':
2025-07-02 04:52:32.071 atags += '^' * la
2025-07-02 04:52:32.071 btags += '^' * lb
2025-07-02 04:52:32.071 elif tag == 'delete':
2025-07-02 04:52:32.071 atags += '-' * la
2025-07-02 04:52:32.071 elif tag == 'insert':
2025-07-02 04:52:32.071 btags += '+' * lb
2025-07-02 04:52:32.071 elif tag == 'equal':
2025-07-02 04:52:32.071 atags += ' ' * la
2025-07-02 04:52:32.071 btags += ' ' * lb
2025-07-02 04:52:32.071 else:
2025-07-02 04:52:32.071 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.072 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.072 else:
2025-07-02 04:52:32.072 # the synch pair is identical
2025-07-02 04:52:32.072 yield ' ' + aelt
2025-07-02 04:52:32.072
2025-07-02 04:52:32.072 # pump out diffs from after the synch point
2025-07-02 04:52:32.072 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.072
2025-07-02 04:52:32.072 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.072 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.072
2025-07-02 04:52:32.072 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.072 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.072 alo = 160, ahi = 1101
2025-07-02 04:52:32.072 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.072 blo = 160, bhi = 1101
2025-07-02 04:52:32.072
2025-07-02 04:52:32.072 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.072 g = []
2025-07-02 04:52:32.072 if alo < ahi:
2025-07-02 04:52:32.073 if blo < bhi:
2025-07-02 04:52:32.073 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.073 else:
2025-07-02 04:52:32.073 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.073 elif blo < bhi:
2025-07-02 04:52:32.073 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.073
2025-07-02 04:52:32.073 > yield from g
2025-07-02 04:52:32.073
2025-07-02 04:52:32.073 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.073 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.073
2025-07-02 04:52:32.073 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.073 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.073 alo = 160, ahi = 1101
2025-07-02 04:52:32.073 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.073 blo = 160, bhi = 1101
2025-07-02 04:52:32.073
2025-07-02 04:52:32.073 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.073 r"""
2025-07-02 04:52:32.073 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.074 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.074 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.074 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.074
2025-07-02 04:52:32.074 Example:
2025-07-02 04:52:32.074
2025-07-02 04:52:32.074 >>> d = Differ()
2025-07-02 04:52:32.074 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.074 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.074 >>> print(''.join(results), end="")
2025-07-02 04:52:32.074 - abcDefghiJkl
2025-07-02 04:52:32.074 + abcdefGhijkl
2025-07-02 04:52:32.074 """
2025-07-02 04:52:32.074
2025-07-02 04:52:32.074 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.074 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.074 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.074 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.074 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.075
2025-07-02 04:52:32.075 # search for the pair that matches best without being identical
2025-07-02 04:52:32.075 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.075 # on junk -- unless we have to)
2025-07-02 04:52:32.075 for j in range(blo, bhi):
2025-07-02 04:52:32.075 bj = b[j]
2025-07-02 04:52:32.075 cruncher.set_seq2(bj)
2025-07-02 04:52:32.075 for i in range(alo, ahi):
2025-07-02 04:52:32.075 ai = a[i]
2025-07-02 04:52:32.075 if ai == bj:
2025-07-02 04:52:32.075 if eqi is None:
2025-07-02 04:52:32.075 eqi, eqj = i, j
2025-07-02 04:52:32.075 continue
2025-07-02 04:52:32.075 cruncher.set_seq1(ai)
2025-07-02 04:52:32.075 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.075 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.075 # compares by a factor of 3.
2025-07-02 04:52:32.075 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.075 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.075 # of the computation is cached by cruncher
2025-07-02 04:52:32.076 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.076 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.076 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.076 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.076 if best_ratio < cutoff:
2025-07-02 04:52:32.076 # no non-identical "pretty close" pair
2025-07-02 04:52:32.076 if eqi is None:
2025-07-02 04:52:32.076 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.076 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.076 return
2025-07-02 04:52:32.076 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.076 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.076 else:
2025-07-02 04:52:32.076 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.076 eqi = None
2025-07-02 04:52:32.076
2025-07-02 04:52:32.076 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.076 # identical
2025-07-02 04:52:32.076
2025-07-02 04:52:32.076 # pump out diffs from before the synch point
2025-07-02 04:52:32.077 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.078
2025-07-02 04:52:32.078 # do intraline marking on the synch pair
2025-07-02 04:52:32.078 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.078 if eqi is None:
2025-07-02 04:52:32.078 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.078 atags = btags = ""
2025-07-02 04:52:32.078 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.078 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.078 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.078 if tag == 'replace':
2025-07-02 04:52:32.078 atags += '^' * la
2025-07-02 04:52:32.078 btags += '^' * lb
2025-07-02 04:52:32.078 elif tag == 'delete':
2025-07-02 04:52:32.078 atags += '-' * la
2025-07-02 04:52:32.078 elif tag == 'insert':
2025-07-02 04:52:32.078 btags += '+' * lb
2025-07-02 04:52:32.078 elif tag == 'equal':
2025-07-02 04:52:32.078 atags += ' ' * la
2025-07-02 04:52:32.078 btags += ' ' * lb
2025-07-02 04:52:32.078 else:
2025-07-02 04:52:32.078 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.079 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.079 else:
2025-07-02 04:52:32.079 # the synch pair is identical
2025-07-02 04:52:32.079 yield ' ' + aelt
2025-07-02 04:52:32.079
2025-07-02 04:52:32.079 # pump out diffs from after the synch point
2025-07-02 04:52:32.079 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.079
2025-07-02 04:52:32.079 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.079 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.079
2025-07-02 04:52:32.079 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.079 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.079 alo = 161, ahi = 1101
2025-07-02 04:52:32.079 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.079 blo = 161, bhi = 1101
2025-07-02 04:52:32.079
2025-07-02 04:52:32.079 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.079 g = []
2025-07-02 04:52:32.079 if alo < ahi:
2025-07-02 04:52:32.080 if blo < bhi:
2025-07-02 04:52:32.080 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.080 else:
2025-07-02 04:52:32.080 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.080 elif blo < bhi:
2025-07-02 04:52:32.080 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.080
2025-07-02 04:52:32.080 > yield from g
2025-07-02 04:52:32.080
2025-07-02 04:52:32.080 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.080 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.080
2025-07-02 04:52:32.080 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.080 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.080 alo = 161, ahi = 1101
2025-07-02 04:52:32.080 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.080 blo = 161, bhi = 1101
2025-07-02 04:52:32.080
2025-07-02 04:52:32.080 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.080 r"""
2025-07-02 04:52:32.080 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.081 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.081 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.081 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.081
2025-07-02 04:52:32.081 Example:
2025-07-02 04:52:32.081
2025-07-02 04:52:32.081 >>> d = Differ()
2025-07-02 04:52:32.081 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.081 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.081 >>> print(''.join(results), end="")
2025-07-02 04:52:32.081 - abcDefghiJkl
2025-07-02 04:52:32.081 + abcdefGhijkl
2025-07-02 04:52:32.081 """
2025-07-02 04:52:32.081
2025-07-02 04:52:32.081 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.081 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.081 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.081 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.081 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.081
2025-07-02 04:52:32.082 # search for the pair that matches best without being identical
2025-07-02 04:52:32.082 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.082 # on junk -- unless we have to)
2025-07-02 04:52:32.082 for j in range(blo, bhi):
2025-07-02 04:52:32.082 bj = b[j]
2025-07-02 04:52:32.082 cruncher.set_seq2(bj)
2025-07-02 04:52:32.082 for i in range(alo, ahi):
2025-07-02 04:52:32.082 ai = a[i]
2025-07-02 04:52:32.082 if ai == bj:
2025-07-02 04:52:32.082 if eqi is None:
2025-07-02 04:52:32.082 eqi, eqj = i, j
2025-07-02 04:52:32.082 continue
2025-07-02 04:52:32.082 cruncher.set_seq1(ai)
2025-07-02 04:52:32.082 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.082 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.082 # compares by a factor of 3.
2025-07-02 04:52:32.082 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.082 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.082 # of the computation is cached by cruncher
2025-07-02 04:52:32.082 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.082 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.083 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.083 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.083 if best_ratio < cutoff:
2025-07-02 04:52:32.083 # no non-identical "pretty close" pair
2025-07-02 04:52:32.083 if eqi is None:
2025-07-02 04:52:32.083 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.083 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.083 return
2025-07-02 04:52:32.083 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.083 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.083 else:
2025-07-02 04:52:32.083 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.083 eqi = None
2025-07-02 04:52:32.083
2025-07-02 04:52:32.083 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.083 # identical
2025-07-02 04:52:32.083
2025-07-02 04:52:32.083 # pump out diffs from before the synch point
2025-07-02 04:52:32.083 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.083
2025-07-02 04:52:32.083 # do intraline marking on the synch pair
2025-07-02 04:52:32.083 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.084 if eqi is None:
2025-07-02 04:52:32.084 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.084 atags = btags = ""
2025-07-02 04:52:32.084 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.084 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.084 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.084 if tag == 'replace':
2025-07-02 04:52:32.084 atags += '^' * la
2025-07-02 04:52:32.084 btags += '^' * lb
2025-07-02 04:52:32.084 elif tag == 'delete':
2025-07-02 04:52:32.084 atags += '-' * la
2025-07-02 04:52:32.084 elif tag == 'insert':
2025-07-02 04:52:32.084 btags += '+' * lb
2025-07-02 04:52:32.084 elif tag == 'equal':
2025-07-02 04:52:32.084 atags += ' ' * la
2025-07-02 04:52:32.084 btags += ' ' * lb
2025-07-02 04:52:32.084 else:
2025-07-02 04:52:32.084 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.084 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.084 else:
2025-07-02 04:52:32.084 # the synch pair is identical
2025-07-02 04:52:32.084 yield ' ' + aelt
2025-07-02 04:52:32.085
2025-07-02 04:52:32.085 # pump out diffs from after the synch point
2025-07-02 04:52:32.085 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.085
2025-07-02 04:52:32.085 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.085 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.085
2025-07-02 04:52:32.085 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.085 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.085 alo = 162, ahi = 1101
2025-07-02 04:52:32.085 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.085 blo = 162, bhi = 1101
2025-07-02 04:52:32.085
2025-07-02 04:52:32.085 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.085 g = []
2025-07-02 04:52:32.085 if alo < ahi:
2025-07-02 04:52:32.085 if blo < bhi:
2025-07-02 04:52:32.085 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.085 else:
2025-07-02 04:52:32.085 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.086 elif blo < bhi:
2025-07-02 04:52:32.086 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.086
2025-07-02 04:52:32.086 > yield from g
2025-07-02 04:52:32.086
2025-07-02 04:52:32.086 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.086 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.086
2025-07-02 04:52:32.086 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.086 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.086 alo = 162, ahi = 1101
2025-07-02 04:52:32.086 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.086 blo = 162, bhi = 1101
2025-07-02 04:52:32.086
2025-07-02 04:52:32.086 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.086 r"""
2025-07-02 04:52:32.086 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.086 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.086 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.086 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.087
2025-07-02 04:52:32.087 Example:
2025-07-02 04:52:32.087
2025-07-02 04:52:32.087 >>> d = Differ()
2025-07-02 04:52:32.087 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.087 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.087 >>> print(''.join(results), end="")
2025-07-02 04:52:32.087 - abcDefghiJkl
2025-07-02 04:52:32.087 + abcdefGhijkl
2025-07-02 04:52:32.087 """
2025-07-02 04:52:32.087
2025-07-02 04:52:32.087 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.087 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.087 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.087 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.087 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.087
2025-07-02 04:52:32.087 # search for the pair that matches best without being identical
2025-07-02 04:52:32.088 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.088 # on junk -- unless we have to)
2025-07-02 04:52:32.088 for j in range(blo, bhi):
2025-07-02 04:52:32.088 bj = b[j]
2025-07-02 04:52:32.088 cruncher.set_seq2(bj)
2025-07-02 04:52:32.088 for i in range(alo, ahi):
2025-07-02 04:52:32.088 ai = a[i]
2025-07-02 04:52:32.088 if ai == bj:
2025-07-02 04:52:32.088 if eqi is None:
2025-07-02 04:52:32.088 eqi, eqj = i, j
2025-07-02 04:52:32.088 continue
2025-07-02 04:52:32.088 cruncher.set_seq1(ai)
2025-07-02 04:52:32.088 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.088 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.088 # compares by a factor of 3.
2025-07-02 04:52:32.088 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.088 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.088 # of the computation is cached by cruncher
2025-07-02 04:52:32.088 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.088 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.089 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.089 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.089 if best_ratio < cutoff:
2025-07-02 04:52:32.089 # no non-identical "pretty close" pair
2025-07-02 04:52:32.089 if eqi is None:
2025-07-02 04:52:32.089 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.089 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.089 return
2025-07-02 04:52:32.089 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.089 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.089 else:
2025-07-02 04:52:32.089 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.089 eqi = None
2025-07-02 04:52:32.089
2025-07-02 04:52:32.089 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.089 # identical
2025-07-02 04:52:32.089
2025-07-02 04:52:32.089 # pump out diffs from before the synch point
2025-07-02 04:52:32.089 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.089
2025-07-02 04:52:32.089 # do intraline marking on the synch pair
2025-07-02 04:52:32.090 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.090 if eqi is None:
2025-07-02 04:52:32.090 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.090 atags = btags = ""
2025-07-02 04:52:32.090 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.090 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.090 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.090 if tag == 'replace':
2025-07-02 04:52:32.090 atags += '^' * la
2025-07-02 04:52:32.090 btags += '^' * lb
2025-07-02 04:52:32.090 elif tag == 'delete':
2025-07-02 04:52:32.090 atags += '-' * la
2025-07-02 04:52:32.090 elif tag == 'insert':
2025-07-02 04:52:32.090 btags += '+' * lb
2025-07-02 04:52:32.090 elif tag == 'equal':
2025-07-02 04:52:32.090 atags += ' ' * la
2025-07-02 04:52:32.090 btags += ' ' * lb
2025-07-02 04:52:32.090 else:
2025-07-02 04:52:32.090 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.090 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.090 else:
2025-07-02 04:52:32.090 # the synch pair is identical
2025-07-02 04:52:32.091 yield ' ' + aelt
2025-07-02 04:52:32.091
2025-07-02 04:52:32.091 # pump out diffs from after the synch point
2025-07-02 04:52:32.091 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.091
2025-07-02 04:52:32.091 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.091 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.091
2025-07-02 04:52:32.091 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.091 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.091 alo = 163, ahi = 1101
2025-07-02 04:52:32.091 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.091 blo = 163, bhi = 1101
2025-07-02 04:52:32.091
2025-07-02 04:52:32.091 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.091 g = []
2025-07-02 04:52:32.091 if alo < ahi:
2025-07-02 04:52:32.091 if blo < bhi:
2025-07-02 04:52:32.091 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.091 else:
2025-07-02 04:52:32.091 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.092 elif blo < bhi:
2025-07-02 04:52:32.092 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.092
2025-07-02 04:52:32.092 > yield from g
2025-07-02 04:52:32.092
2025-07-02 04:52:32.092 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.092 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.092
2025-07-02 04:52:32.092 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.092 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.092 alo = 163, ahi = 1101
2025-07-02 04:52:32.092 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.092 blo = 163, bhi = 1101
2025-07-02 04:52:32.092
2025-07-02 04:52:32.092 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.092 r"""
2025-07-02 04:52:32.092 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.092 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.092 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.092 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.092
2025-07-02 04:52:32.092 Example:
2025-07-02 04:52:32.093
2025-07-02 04:52:32.093 >>> d = Differ()
2025-07-02 04:52:32.093 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.093 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.093 >>> print(''.join(results), end="")
2025-07-02 04:52:32.093 - abcDefghiJkl
2025-07-02 04:52:32.093 + abcdefGhijkl
2025-07-02 04:52:32.093 """
2025-07-02 04:52:32.093
2025-07-02 04:52:32.093 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.093 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.093 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.093 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.093 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.093
2025-07-02 04:52:32.093 # search for the pair that matches best without being identical
2025-07-02 04:52:32.093 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.094 # on junk -- unless we have to)
2025-07-02 04:52:32.094 for j in range(blo, bhi):
2025-07-02 04:52:32.094 bj = b[j]
2025-07-02 04:52:32.094 cruncher.set_seq2(bj)
2025-07-02 04:52:32.094 for i in range(alo, ahi):
2025-07-02 04:52:32.094 ai = a[i]
2025-07-02 04:52:32.094 if ai == bj:
2025-07-02 04:52:32.094 if eqi is None:
2025-07-02 04:52:32.094 eqi, eqj = i, j
2025-07-02 04:52:32.094 continue
2025-07-02 04:52:32.094 cruncher.set_seq1(ai)
2025-07-02 04:52:32.094 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.094 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.094 # compares by a factor of 3.
2025-07-02 04:52:32.094 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.094 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.094 # of the computation is cached by cruncher
2025-07-02 04:52:32.094 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.094 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.094 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.095 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.095 if best_ratio < cutoff:
2025-07-02 04:52:32.095 # no non-identical "pretty close" pair
2025-07-02 04:52:32.095 if eqi is None:
2025-07-02 04:52:32.095 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.095 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.095 return
2025-07-02 04:52:32.095 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.095 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.095 else:
2025-07-02 04:52:32.095 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.095 eqi = None
2025-07-02 04:52:32.095
2025-07-02 04:52:32.095 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.095 # identical
2025-07-02 04:52:32.095
2025-07-02 04:52:32.095 # pump out diffs from before the synch point
2025-07-02 04:52:32.095 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.095
2025-07-02 04:52:32.095 # do intraline marking on the synch pair
2025-07-02 04:52:32.095 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.096 if eqi is None:
2025-07-02 04:52:32.096 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.096 atags = btags = ""
2025-07-02 04:52:32.096 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.096 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.096 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.096 if tag == 'replace':
2025-07-02 04:52:32.096 atags += '^' * la
2025-07-02 04:52:32.096 btags += '^' * lb
2025-07-02 04:52:32.096 elif tag == 'delete':
2025-07-02 04:52:32.096 atags += '-' * la
2025-07-02 04:52:32.096 elif tag == 'insert':
2025-07-02 04:52:32.096 btags += '+' * lb
2025-07-02 04:52:32.096 elif tag == 'equal':
2025-07-02 04:52:32.096 atags += ' ' * la
2025-07-02 04:52:32.096 btags += ' ' * lb
2025-07-02 04:52:32.096 else:
2025-07-02 04:52:32.096 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.096 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.096 else:
2025-07-02 04:52:32.096 # the synch pair is identical
2025-07-02 04:52:32.096 yield ' ' + aelt
2025-07-02 04:52:32.097
2025-07-02 04:52:32.097 # pump out diffs from after the synch point
2025-07-02 04:52:32.097 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.097
2025-07-02 04:52:32.097 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.097 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.097
2025-07-02 04:52:32.097 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.097 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.097 alo = 164, ahi = 1101
2025-07-02 04:52:32.097 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.097 blo = 164, bhi = 1101
2025-07-02 04:52:32.097
2025-07-02 04:52:32.097 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.097 g = []
2025-07-02 04:52:32.097 if alo < ahi:
2025-07-02 04:52:32.097 if blo < bhi:
2025-07-02 04:52:32.097 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.097 else:
2025-07-02 04:52:32.097 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.097 elif blo < bhi:
2025-07-02 04:52:32.098 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.098
2025-07-02 04:52:32.098 > yield from g
2025-07-02 04:52:32.098
2025-07-02 04:52:32.098 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.098 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.098
2025-07-02 04:52:32.098 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.098 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.098 alo = 164, ahi = 1101
2025-07-02 04:52:32.098 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.098 blo = 164, bhi = 1101
2025-07-02 04:52:32.098
2025-07-02 04:52:32.098 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.098 r"""
2025-07-02 04:52:32.098 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.098 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.098 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.098 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.098
2025-07-02 04:52:32.098 Example:
2025-07-02 04:52:32.099
2025-07-02 04:52:32.099 >>> d = Differ()
2025-07-02 04:52:32.099 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.099 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.099 >>> print(''.join(results), end="")
2025-07-02 04:52:32.099 - abcDefghiJkl
2025-07-02 04:52:32.099 + abcdefGhijkl
2025-07-02 04:52:32.099 """
2025-07-02 04:52:32.099
2025-07-02 04:52:32.099 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.099 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.099 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.099 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.099 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.099
2025-07-02 04:52:32.099 # search for the pair that matches best without being identical
2025-07-02 04:52:32.099 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.099 # on junk -- unless we have to)
2025-07-02 04:52:32.099 for j in range(blo, bhi):
2025-07-02 04:52:32.099 bj = b[j]
2025-07-02 04:52:32.100 cruncher.set_seq2(bj)
2025-07-02 04:52:32.100 for i in range(alo, ahi):
2025-07-02 04:52:32.100 ai = a[i]
2025-07-02 04:52:32.100 if ai == bj:
2025-07-02 04:52:32.100 if eqi is None:
2025-07-02 04:52:32.100 eqi, eqj = i, j
2025-07-02 04:52:32.100 continue
2025-07-02 04:52:32.100 cruncher.set_seq1(ai)
2025-07-02 04:52:32.100 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.100 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.100 # compares by a factor of 3.
2025-07-02 04:52:32.100 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.100 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.100 # of the computation is cached by cruncher
2025-07-02 04:52:32.100 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.100 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.100 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.100 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.100 if best_ratio < cutoff:
2025-07-02 04:52:32.100 # no non-identical "pretty close" pair
2025-07-02 04:52:32.100 if eqi is None:
2025-07-02 04:52:32.101 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.101 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.101 return
2025-07-02 04:52:32.101 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.101 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.101 else:
2025-07-02 04:52:32.101 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.101 eqi = None
2025-07-02 04:52:32.101
2025-07-02 04:52:32.101 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.101 # identical
2025-07-02 04:52:32.101
2025-07-02 04:52:32.101 # pump out diffs from before the synch point
2025-07-02 04:52:32.101 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.101
2025-07-02 04:52:32.101 # do intraline marking on the synch pair
2025-07-02 04:52:32.101 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.101 if eqi is None:
2025-07-02 04:52:32.101 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.101 atags = btags = ""
2025-07-02 04:52:32.101 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.102 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.102 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.102 if tag == 'replace':
2025-07-02 04:52:32.102 atags += '^' * la
2025-07-02 04:52:32.102 btags += '^' * lb
2025-07-02 04:52:32.102 elif tag == 'delete':
2025-07-02 04:52:32.102 atags += '-' * la
2025-07-02 04:52:32.102 elif tag == 'insert':
2025-07-02 04:52:32.102 btags += '+' * lb
2025-07-02 04:52:32.102 elif tag == 'equal':
2025-07-02 04:52:32.102 atags += ' ' * la
2025-07-02 04:52:32.102 btags += ' ' * lb
2025-07-02 04:52:32.102 else:
2025-07-02 04:52:32.102 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.102 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.102 else:
2025-07-02 04:52:32.102 # the synch pair is identical
2025-07-02 04:52:32.102 yield ' ' + aelt
2025-07-02 04:52:32.102
2025-07-02 04:52:32.102 # pump out diffs from after the synch point
2025-07-02 04:52:32.103 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.103
2025-07-02 04:52:32.103 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.103 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.103
2025-07-02 04:52:32.103 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.103 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.103 alo = 165, ahi = 1101
2025-07-02 04:52:32.103 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.103 blo = 165, bhi = 1101
2025-07-02 04:52:32.103
2025-07-02 04:52:32.103 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.103 g = []
2025-07-02 04:52:32.103 if alo < ahi:
2025-07-02 04:52:32.103 if blo < bhi:
2025-07-02 04:52:32.103 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.103 else:
2025-07-02 04:52:32.103 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.103 elif blo < bhi:
2025-07-02 04:52:32.103 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.104
2025-07-02 04:52:32.104 > yield from g
2025-07-02 04:52:32.104
2025-07-02 04:52:32.104 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.104 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.104
2025-07-02 04:52:32.104 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.104 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.104 alo = 165, ahi = 1101
2025-07-02 04:52:32.104 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.104 blo = 165, bhi = 1101
2025-07-02 04:52:32.104
2025-07-02 04:52:32.104 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.104 r"""
2025-07-02 04:52:32.104 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.104 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.104 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.104 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.104
2025-07-02 04:52:32.104 Example:
2025-07-02 04:52:32.104
2025-07-02 04:52:32.105 >>> d = Differ()
2025-07-02 04:52:32.105 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.105 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.105 >>> print(''.join(results), end="")
2025-07-02 04:52:32.105 - abcDefghiJkl
2025-07-02 04:52:32.105 + abcdefGhijkl
2025-07-02 04:52:32.105 """
2025-07-02 04:52:32.105
2025-07-02 04:52:32.105 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.105 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.105 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.105 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.105 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.105
2025-07-02 04:52:32.105 # search for the pair that matches best without being identical
2025-07-02 04:52:32.105 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.105 # on junk -- unless we have to)
2025-07-02 04:52:32.106 for j in range(blo, bhi):
2025-07-02 04:52:32.106 bj = b[j]
2025-07-02 04:52:32.106 cruncher.set_seq2(bj)
2025-07-02 04:52:32.106 for i in range(alo, ahi):
2025-07-02 04:52:32.106 ai = a[i]
2025-07-02 04:52:32.106 if ai == bj:
2025-07-02 04:52:32.106 if eqi is None:
2025-07-02 04:52:32.106 eqi, eqj = i, j
2025-07-02 04:52:32.106 continue
2025-07-02 04:52:32.106 cruncher.set_seq1(ai)
2025-07-02 04:52:32.106 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.106 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.106 # compares by a factor of 3.
2025-07-02 04:52:32.106 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.106 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.106 # of the computation is cached by cruncher
2025-07-02 04:52:32.106 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.106 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.106 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.106 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.107 if best_ratio < cutoff:
2025-07-02 04:52:32.107 # no non-identical "pretty close" pair
2025-07-02 04:52:32.107 if eqi is None:
2025-07-02 04:52:32.107 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.107 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.107 return
2025-07-02 04:52:32.107 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.107 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.107 else:
2025-07-02 04:52:32.107 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.107 eqi = None
2025-07-02 04:52:32.107
2025-07-02 04:52:32.107 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.107 # identical
2025-07-02 04:52:32.107
2025-07-02 04:52:32.107 # pump out diffs from before the synch point
2025-07-02 04:52:32.107 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.107
2025-07-02 04:52:32.107 # do intraline marking on the synch pair
2025-07-02 04:52:32.107 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.107 if eqi is None:
2025-07-02 04:52:32.108 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.108 atags = btags = ""
2025-07-02 04:52:32.108 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.108 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.108 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.108 if tag == 'replace':
2025-07-02 04:52:32.108 atags += '^' * la
2025-07-02 04:52:32.108 btags += '^' * lb
2025-07-02 04:52:32.108 elif tag == 'delete':
2025-07-02 04:52:32.108 atags += '-' * la
2025-07-02 04:52:32.108 elif tag == 'insert':
2025-07-02 04:52:32.108 btags += '+' * lb
2025-07-02 04:52:32.108 elif tag == 'equal':
2025-07-02 04:52:32.108 atags += ' ' * la
2025-07-02 04:52:32.108 btags += ' ' * lb
2025-07-02 04:52:32.108 else:
2025-07-02 04:52:32.108 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.108 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.108 else:
2025-07-02 04:52:32.108 # the synch pair is identical
2025-07-02 04:52:32.108 yield ' ' + aelt
2025-07-02 04:52:32.109
2025-07-02 04:52:32.109 # pump out diffs from after the synch point
2025-07-02 04:52:32.109 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.109
2025-07-02 04:52:32.109 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.109 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.109
2025-07-02 04:52:32.109 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.109 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.109 alo = 166, ahi = 1101
2025-07-02 04:52:32.109 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.109 blo = 166, bhi = 1101
2025-07-02 04:52:32.109
2025-07-02 04:52:32.109 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.109 g = []
2025-07-02 04:52:32.109 if alo < ahi:
2025-07-02 04:52:32.109 if blo < bhi:
2025-07-02 04:52:32.109 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.109 else:
2025-07-02 04:52:32.109 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.109 elif blo < bhi:
2025-07-02 04:52:32.110 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.110
2025-07-02 04:52:32.110 > yield from g
2025-07-02 04:52:32.110
2025-07-02 04:52:32.110 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.110 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.110
2025-07-02 04:52:32.110 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.110 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.110 alo = 166, ahi = 1101
2025-07-02 04:52:32.110 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.110 blo = 166, bhi = 1101
2025-07-02 04:52:32.110
2025-07-02 04:52:32.110 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.110 r"""
2025-07-02 04:52:32.110 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.110 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.110 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.110 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.111
2025-07-02 04:52:32.111 Example:
2025-07-02 04:52:32.111
2025-07-02 04:52:32.111 >>> d = Differ()
2025-07-02 04:52:32.111 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.111 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.111 >>> print(''.join(results), end="")
2025-07-02 04:52:32.111 - abcDefghiJkl
2025-07-02 04:52:32.111 + abcdefGhijkl
2025-07-02 04:52:32.111 """
2025-07-02 04:52:32.111
2025-07-02 04:52:32.111 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.111 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.111 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.111 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.111 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.111
2025-07-02 04:52:32.111 # search for the pair that matches best without being identical
2025-07-02 04:52:32.111 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.112 # on junk -- unless we have to)
2025-07-02 04:52:32.112 for j in range(blo, bhi):
2025-07-02 04:52:32.112 bj = b[j]
2025-07-02 04:52:32.112 cruncher.set_seq2(bj)
2025-07-02 04:52:32.112 for i in range(alo, ahi):
2025-07-02 04:52:32.112 ai = a[i]
2025-07-02 04:52:32.112 if ai == bj:
2025-07-02 04:52:32.112 if eqi is None:
2025-07-02 04:52:32.112 eqi, eqj = i, j
2025-07-02 04:52:32.112 continue
2025-07-02 04:52:32.112 cruncher.set_seq1(ai)
2025-07-02 04:52:32.112 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.112 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.112 # compares by a factor of 3.
2025-07-02 04:52:32.112 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.112 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.112 # of the computation is cached by cruncher
2025-07-02 04:52:32.112 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.112 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.112 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.112 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.113 if best_ratio < cutoff:
2025-07-02 04:52:32.113 # no non-identical "pretty close" pair
2025-07-02 04:52:32.113 if eqi is None:
2025-07-02 04:52:32.113 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.113 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.113 return
2025-07-02 04:52:32.113 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.113 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.113 else:
2025-07-02 04:52:32.113 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.113 eqi = None
2025-07-02 04:52:32.113
2025-07-02 04:52:32.113 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.113 # identical
2025-07-02 04:52:32.113
2025-07-02 04:52:32.113 # pump out diffs from before the synch point
2025-07-02 04:52:32.113 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.113
2025-07-02 04:52:32.113 # do intraline marking on the synch pair
2025-07-02 04:52:32.113 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.113 if eqi is None:
2025-07-02 04:52:32.114 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.114 atags = btags = ""
2025-07-02 04:52:32.114 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.114 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.114 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.114 if tag == 'replace':
2025-07-02 04:52:32.114 atags += '^' * la
2025-07-02 04:52:32.114 btags += '^' * lb
2025-07-02 04:52:32.114 elif tag == 'delete':
2025-07-02 04:52:32.114 atags += '-' * la
2025-07-02 04:52:32.114 elif tag == 'insert':
2025-07-02 04:52:32.114 btags += '+' * lb
2025-07-02 04:52:32.114 elif tag == 'equal':
2025-07-02 04:52:32.114 atags += ' ' * la
2025-07-02 04:52:32.114 btags += ' ' * lb
2025-07-02 04:52:32.114 else:
2025-07-02 04:52:32.114 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.114 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.114 else:
2025-07-02 04:52:32.114 # the synch pair is identical
2025-07-02 04:52:32.114 yield ' ' + aelt
2025-07-02 04:52:32.114
2025-07-02 04:52:32.115 # pump out diffs from after the synch point
2025-07-02 04:52:32.115 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.115
2025-07-02 04:52:32.115 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.115 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.115
2025-07-02 04:52:32.115 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.115 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.115 alo = 167, ahi = 1101
2025-07-02 04:52:32.115 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.115 blo = 167, bhi = 1101
2025-07-02 04:52:32.115
2025-07-02 04:52:32.115 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.115 g = []
2025-07-02 04:52:32.115 if alo < ahi:
2025-07-02 04:52:32.115 if blo < bhi:
2025-07-02 04:52:32.115 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.115 else:
2025-07-02 04:52:32.115 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.115 elif blo < bhi:
2025-07-02 04:52:32.115 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.116
2025-07-02 04:52:32.116 > yield from g
2025-07-02 04:52:32.116
2025-07-02 04:52:32.116 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.116 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.116
2025-07-02 04:52:32.116 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.116 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.116 alo = 167, ahi = 1101
2025-07-02 04:52:32.116 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.116 blo = 167, bhi = 1101
2025-07-02 04:52:32.116
2025-07-02 04:52:32.116 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.116 r"""
2025-07-02 04:52:32.116 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.116 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.116 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.116 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.116
2025-07-02 04:52:32.116 Example:
2025-07-02 04:52:32.116
2025-07-02 04:52:32.116 >>> d = Differ()
2025-07-02 04:52:32.117 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.117 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.117 >>> print(''.join(results), end="")
2025-07-02 04:52:32.117 - abcDefghiJkl
2025-07-02 04:52:32.117 + abcdefGhijkl
2025-07-02 04:52:32.117 """
2025-07-02 04:52:32.117
2025-07-02 04:52:32.117 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.117 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.117 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.117 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.117 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.117
2025-07-02 04:52:32.117 # search for the pair that matches best without being identical
2025-07-02 04:52:32.117 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.117 # on junk -- unless we have to)
2025-07-02 04:52:32.117 for j in range(blo, bhi):
2025-07-02 04:52:32.117 bj = b[j]
2025-07-02 04:52:32.117 cruncher.set_seq2(bj)
2025-07-02 04:52:32.117 for i in range(alo, ahi):
2025-07-02 04:52:32.118 ai = a[i]
2025-07-02 04:52:32.118 if ai == bj:
2025-07-02 04:52:32.118 if eqi is None:
2025-07-02 04:52:32.118 eqi, eqj = i, j
2025-07-02 04:52:32.118 continue
2025-07-02 04:52:32.118 cruncher.set_seq1(ai)
2025-07-02 04:52:32.118 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.118 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.118 # compares by a factor of 3.
2025-07-02 04:52:32.118 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.118 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.118 # of the computation is cached by cruncher
2025-07-02 04:52:32.118 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.118 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.118 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.118 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.118 if best_ratio < cutoff:
2025-07-02 04:52:32.118 # no non-identical "pretty close" pair
2025-07-02 04:52:32.119 if eqi is None:
2025-07-02 04:52:32.119 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.119 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.119 return
2025-07-02 04:52:32.119 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.119 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.119 else:
2025-07-02 04:52:32.119 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.119 eqi = None
2025-07-02 04:52:32.119
2025-07-02 04:52:32.119 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.119 # identical
2025-07-02 04:52:32.119
2025-07-02 04:52:32.119 # pump out diffs from before the synch point
2025-07-02 04:52:32.119 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.119
2025-07-02 04:52:32.119 # do intraline marking on the synch pair
2025-07-02 04:52:32.119 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.119 if eqi is None:
2025-07-02 04:52:32.119 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.119 atags = btags = ""
2025-07-02 04:52:32.120 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.120 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.120 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.120 if tag == 'replace':
2025-07-02 04:52:32.120 atags += '^' * la
2025-07-02 04:52:32.120 btags += '^' * lb
2025-07-02 04:52:32.120 elif tag == 'delete':
2025-07-02 04:52:32.120 atags += '-' * la
2025-07-02 04:52:32.120 elif tag == 'insert':
2025-07-02 04:52:32.120 btags += '+' * lb
2025-07-02 04:52:32.120 elif tag == 'equal':
2025-07-02 04:52:32.120 atags += ' ' * la
2025-07-02 04:52:32.120 btags += ' ' * lb
2025-07-02 04:52:32.120 else:
2025-07-02 04:52:32.120 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.120 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.120 else:
2025-07-02 04:52:32.120 # the synch pair is identical
2025-07-02 04:52:32.120 yield ' ' + aelt
2025-07-02 04:52:32.120
2025-07-02 04:52:32.120 # pump out diffs from after the synch point
2025-07-02 04:52:32.121 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.121
2025-07-02 04:52:32.121 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.121 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.121
2025-07-02 04:52:32.121 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.121 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.121 alo = 168, ahi = 1101
2025-07-02 04:52:32.121 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.121 blo = 168, bhi = 1101
2025-07-02 04:52:32.121
2025-07-02 04:52:32.121 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.121 g = []
2025-07-02 04:52:32.121 if alo < ahi:
2025-07-02 04:52:32.121 if blo < bhi:
2025-07-02 04:52:32.121 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.121 else:
2025-07-02 04:52:32.121 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.121 elif blo < bhi:
2025-07-02 04:52:32.121 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.121
2025-07-02 04:52:32.122 > yield from g
2025-07-02 04:52:32.122
2025-07-02 04:52:32.122 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.122 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.122
2025-07-02 04:52:32.122 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.122 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.122 alo = 168, ahi = 1101
2025-07-02 04:52:32.122 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.122 blo = 168, bhi = 1101
2025-07-02 04:52:32.122
2025-07-02 04:52:32.122 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.122 r"""
2025-07-02 04:52:32.122 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.122 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.122 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.122 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.122
2025-07-02 04:52:32.122 Example:
2025-07-02 04:52:32.122
2025-07-02 04:52:32.122 >>> d = Differ()
2025-07-02 04:52:32.122 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.123 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.123 >>> print(''.join(results), end="")
2025-07-02 04:52:32.123 - abcDefghiJkl
2025-07-02 04:52:32.123 + abcdefGhijkl
2025-07-02 04:52:32.123 """
2025-07-02 04:52:32.123
2025-07-02 04:52:32.123 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.123 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.123 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.123 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.123 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.123
2025-07-02 04:52:32.123 # search for the pair that matches best without being identical
2025-07-02 04:52:32.123 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.123 # on junk -- unless we have to)
2025-07-02 04:52:32.123 for j in range(blo, bhi):
2025-07-02 04:52:32.123 bj = b[j]
2025-07-02 04:52:32.123 cruncher.set_seq2(bj)
2025-07-02 04:52:32.123 for i in range(alo, ahi):
2025-07-02 04:52:32.124 ai = a[i]
2025-07-02 04:52:32.124 if ai == bj:
2025-07-02 04:52:32.124 if eqi is None:
2025-07-02 04:52:32.124 eqi, eqj = i, j
2025-07-02 04:52:32.124 continue
2025-07-02 04:52:32.124 cruncher.set_seq1(ai)
2025-07-02 04:52:32.124 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.124 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.124 # compares by a factor of 3.
2025-07-02 04:52:32.124 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.124 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.124 # of the computation is cached by cruncher
2025-07-02 04:52:32.124 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.124 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.124 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.124 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.124 if best_ratio < cutoff:
2025-07-02 04:52:32.124 # no non-identical "pretty close" pair
2025-07-02 04:52:32.124 if eqi is None:
2025-07-02 04:52:32.124 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.124 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.125 return
2025-07-02 04:52:32.125 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.125 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.125 else:
2025-07-02 04:52:32.125 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.125 eqi = None
2025-07-02 04:52:32.125
2025-07-02 04:52:32.125 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.125 # identical
2025-07-02 04:52:32.125
2025-07-02 04:52:32.125 # pump out diffs from before the synch point
2025-07-02 04:52:32.125 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.125
2025-07-02 04:52:32.125 # do intraline marking on the synch pair
2025-07-02 04:52:32.125 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.125 if eqi is None:
2025-07-02 04:52:32.125 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.125 atags = btags = ""
2025-07-02 04:52:32.125 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.125 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.125 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.126 if tag == 'replace':
2025-07-02 04:52:32.126 atags += '^' * la
2025-07-02 04:52:32.126 btags += '^' * lb
2025-07-02 04:52:32.126 elif tag == 'delete':
2025-07-02 04:52:32.126 atags += '-' * la
2025-07-02 04:52:32.126 elif tag == 'insert':
2025-07-02 04:52:32.126 btags += '+' * lb
2025-07-02 04:52:32.126 elif tag == 'equal':
2025-07-02 04:52:32.126 atags += ' ' * la
2025-07-02 04:52:32.126 btags += ' ' * lb
2025-07-02 04:52:32.126 else:
2025-07-02 04:52:32.126 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.126 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.126 else:
2025-07-02 04:52:32.126 # the synch pair is identical
2025-07-02 04:52:32.126 yield ' ' + aelt
2025-07-02 04:52:32.126
2025-07-02 04:52:32.126 # pump out diffs from after the synch point
2025-07-02 04:52:32.126 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.126
2025-07-02 04:52:32.126 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.127 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.127
2025-07-02 04:52:32.127 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.127 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.127 alo = 169, ahi = 1101
2025-07-02 04:52:32.127 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.127 blo = 169, bhi = 1101
2025-07-02 04:52:32.127
2025-07-02 04:52:32.127 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.127 g = []
2025-07-02 04:52:32.127 if alo < ahi:
2025-07-02 04:52:32.127 if blo < bhi:
2025-07-02 04:52:32.127 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.127 else:
2025-07-02 04:52:32.127 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.127 elif blo < bhi:
2025-07-02 04:52:32.127 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.127
2025-07-02 04:52:32.127 > yield from g
2025-07-02 04:52:32.127
2025-07-02 04:52:32.128 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.128 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.128
2025-07-02 04:52:32.128 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.128 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.128 alo = 169, ahi = 1101
2025-07-02 04:52:32.128 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.128 blo = 169, bhi = 1101
2025-07-02 04:52:32.128
2025-07-02 04:52:32.128 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.128 r"""
2025-07-02 04:52:32.128 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.128 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.128 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.128 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.128
2025-07-02 04:52:32.128 Example:
2025-07-02 04:52:32.128
2025-07-02 04:52:32.128 >>> d = Differ()
2025-07-02 04:52:32.128 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.128 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.129 >>> print(''.join(results), end="")
2025-07-02 04:52:32.129 - abcDefghiJkl
2025-07-02 04:52:32.129 + abcdefGhijkl
2025-07-02 04:52:32.129 """
2025-07-02 04:52:32.129
2025-07-02 04:52:32.129 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.129 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.129 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.129 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.129 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.129
2025-07-02 04:52:32.129 # search for the pair that matches best without being identical
2025-07-02 04:52:32.129 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.129 # on junk -- unless we have to)
2025-07-02 04:52:32.129 for j in range(blo, bhi):
2025-07-02 04:52:32.129 bj = b[j]
2025-07-02 04:52:32.129 cruncher.set_seq2(bj)
2025-07-02 04:52:32.129 for i in range(alo, ahi):
2025-07-02 04:52:32.129 ai = a[i]
2025-07-02 04:52:32.130 if ai == bj:
2025-07-02 04:52:32.130 if eqi is None:
2025-07-02 04:52:32.130 eqi, eqj = i, j
2025-07-02 04:52:32.130 continue
2025-07-02 04:52:32.130 cruncher.set_seq1(ai)
2025-07-02 04:52:32.130 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.130 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.130 # compares by a factor of 3.
2025-07-02 04:52:32.130 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.130 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.130 # of the computation is cached by cruncher
2025-07-02 04:52:32.130 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.130 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.130 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.130 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.130 if best_ratio < cutoff:
2025-07-02 04:52:32.130 # no non-identical "pretty close" pair
2025-07-02 04:52:32.130 if eqi is None:
2025-07-02 04:52:32.130 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.130 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.130 return
2025-07-02 04:52:32.130 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.131 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.131 else:
2025-07-02 04:52:32.131 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.131 eqi = None
2025-07-02 04:52:32.131
2025-07-02 04:52:32.131 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.131 # identical
2025-07-02 04:52:32.131
2025-07-02 04:52:32.131 # pump out diffs from before the synch point
2025-07-02 04:52:32.131 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.131
2025-07-02 04:52:32.131 # do intraline marking on the synch pair
2025-07-02 04:52:32.131 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.131 if eqi is None:
2025-07-02 04:52:32.131 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.131 atags = btags = ""
2025-07-02 04:52:32.131 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.131 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.131 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.131 if tag == 'replace':
2025-07-02 04:52:32.131 atags += '^' * la
2025-07-02 04:52:32.132 btags += '^' * lb
2025-07-02 04:52:32.132 elif tag == 'delete':
2025-07-02 04:52:32.132 atags += '-' * la
2025-07-02 04:52:32.132 elif tag == 'insert':
2025-07-02 04:52:32.132 btags += '+' * lb
2025-07-02 04:52:32.132 elif tag == 'equal':
2025-07-02 04:52:32.132 atags += ' ' * la
2025-07-02 04:52:32.132 btags += ' ' * lb
2025-07-02 04:52:32.132 else:
2025-07-02 04:52:32.132 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.132 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.132 else:
2025-07-02 04:52:32.132 # the synch pair is identical
2025-07-02 04:52:32.132 yield ' ' + aelt
2025-07-02 04:52:32.132
2025-07-02 04:52:32.132 # pump out diffs from after the synch point
2025-07-02 04:52:32.132 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.132
2025-07-02 04:52:32.132 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.132 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.132
2025-07-02 04:52:32.132 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.133 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.133 alo = 170, ahi = 1101
2025-07-02 04:52:32.133 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.133 blo = 170, bhi = 1101
2025-07-02 04:52:32.133
2025-07-02 04:52:32.133 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.133 g = []
2025-07-02 04:52:32.133 if alo < ahi:
2025-07-02 04:52:32.133 if blo < bhi:
2025-07-02 04:52:32.133 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.133 else:
2025-07-02 04:52:32.133 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.133 elif blo < bhi:
2025-07-02 04:52:32.133 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.133
2025-07-02 04:52:32.133 > yield from g
2025-07-02 04:52:32.133
2025-07-02 04:52:32.133 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.133 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.133
2025-07-02 04:52:32.133 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.134 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.134 alo = 170, ahi = 1101
2025-07-02 04:52:32.134 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.134 blo = 170, bhi = 1101
2025-07-02 04:52:32.134
2025-07-02 04:52:32.134 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.134 r"""
2025-07-02 04:52:32.134 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.134 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.134 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.134 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.134
2025-07-02 04:52:32.134 Example:
2025-07-02 04:52:32.134
2025-07-02 04:52:32.134 >>> d = Differ()
2025-07-02 04:52:32.134 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.134 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.134 >>> print(''.join(results), end="")
2025-07-02 04:52:32.134 - abcDefghiJkl
2025-07-02 04:52:32.135 + abcdefGhijkl
2025-07-02 04:52:32.135 """
2025-07-02 04:52:32.135
2025-07-02 04:52:32.135 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.135 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.135 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.135 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.135 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.135
2025-07-02 04:52:32.135 # search for the pair that matches best without being identical
2025-07-02 04:52:32.135 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.135 # on junk -- unless we have to)
2025-07-02 04:52:32.135 for j in range(blo, bhi):
2025-07-02 04:52:32.135 bj = b[j]
2025-07-02 04:52:32.135 cruncher.set_seq2(bj)
2025-07-02 04:52:32.135 for i in range(alo, ahi):
2025-07-02 04:52:32.135 ai = a[i]
2025-07-02 04:52:32.136 if ai == bj:
2025-07-02 04:52:32.136 if eqi is None:
2025-07-02 04:52:32.136 eqi, eqj = i, j
2025-07-02 04:52:32.136 continue
2025-07-02 04:52:32.136 cruncher.set_seq1(ai)
2025-07-02 04:52:32.136 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.136 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.136 # compares by a factor of 3.
2025-07-02 04:52:32.136 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.136 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.136 # of the computation is cached by cruncher
2025-07-02 04:52:32.136 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.136 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.136 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.136 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.136 if best_ratio < cutoff:
2025-07-02 04:52:32.136 # no non-identical "pretty close" pair
2025-07-02 04:52:32.136 if eqi is None:
2025-07-02 04:52:32.136 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.136 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.136 return
2025-07-02 04:52:32.137 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.137 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.137 else:
2025-07-02 04:52:32.137 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.137 eqi = None
2025-07-02 04:52:32.137
2025-07-02 04:52:32.137 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.137 # identical
2025-07-02 04:52:32.137
2025-07-02 04:52:32.137 # pump out diffs from before the synch point
2025-07-02 04:52:32.137 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.137
2025-07-02 04:52:32.137 # do intraline marking on the synch pair
2025-07-02 04:52:32.137 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.137 if eqi is None:
2025-07-02 04:52:32.137 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.137 atags = btags = ""
2025-07-02 04:52:32.137 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.137 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.137 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.137 if tag == 'replace':
2025-07-02 04:52:32.138 atags += '^' * la
2025-07-02 04:52:32.138 btags += '^' * lb
2025-07-02 04:52:32.138 elif tag == 'delete':
2025-07-02 04:52:32.138 atags += '-' * la
2025-07-02 04:52:32.138 elif tag == 'insert':
2025-07-02 04:52:32.138 btags += '+' * lb
2025-07-02 04:52:32.138 elif tag == 'equal':
2025-07-02 04:52:32.138 atags += ' ' * la
2025-07-02 04:52:32.138 btags += ' ' * lb
2025-07-02 04:52:32.138 else:
2025-07-02 04:52:32.138 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.138 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.138 else:
2025-07-02 04:52:32.138 # the synch pair is identical
2025-07-02 04:52:32.138 yield ' ' + aelt
2025-07-02 04:52:32.138
2025-07-02 04:52:32.138 # pump out diffs from after the synch point
2025-07-02 04:52:32.138 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.138
2025-07-02 04:52:32.138 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.138 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.139
2025-07-02 04:52:32.139 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.139 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.139 alo = 171, ahi = 1101
2025-07-02 04:52:32.139 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.139 blo = 171, bhi = 1101
2025-07-02 04:52:32.139
2025-07-02 04:52:32.139 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.139 g = []
2025-07-02 04:52:32.139 if alo < ahi:
2025-07-02 04:52:32.139 if blo < bhi:
2025-07-02 04:52:32.139 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.139 else:
2025-07-02 04:52:32.139 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.139 elif blo < bhi:
2025-07-02 04:52:32.139 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.139
2025-07-02 04:52:32.139 > yield from g
2025-07-02 04:52:32.139
2025-07-02 04:52:32.139 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.139 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.139
2025-07-02 04:52:32.140 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.140 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.140 alo = 171, ahi = 1101
2025-07-02 04:52:32.140 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.140 blo = 171, bhi = 1101
2025-07-02 04:52:32.140
2025-07-02 04:52:32.140 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.140 r"""
2025-07-02 04:52:32.140 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.140 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.140 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.140 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.140
2025-07-02 04:52:32.140 Example:
2025-07-02 04:52:32.140
2025-07-02 04:52:32.140 >>> d = Differ()
2025-07-02 04:52:32.140 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.140 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.140 >>> print(''.join(results), end="")
2025-07-02 04:52:32.140 - abcDefghiJkl
2025-07-02 04:52:32.141 + abcdefGhijkl
2025-07-02 04:52:32.141 """
2025-07-02 04:52:32.141
2025-07-02 04:52:32.141 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.141 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.141 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.141 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.141 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.141
2025-07-02 04:52:32.141 # search for the pair that matches best without being identical
2025-07-02 04:52:32.141 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.141 # on junk -- unless we have to)
2025-07-02 04:52:32.141 for j in range(blo, bhi):
2025-07-02 04:52:32.141 bj = b[j]
2025-07-02 04:52:32.141 cruncher.set_seq2(bj)
2025-07-02 04:52:32.141 for i in range(alo, ahi):
2025-07-02 04:52:32.141 ai = a[i]
2025-07-02 04:52:32.141 if ai == bj:
2025-07-02 04:52:32.141 if eqi is None:
2025-07-02 04:52:32.141 eqi, eqj = i, j
2025-07-02 04:52:32.142 continue
2025-07-02 04:52:32.142 cruncher.set_seq1(ai)
2025-07-02 04:52:32.142 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.142 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.142 # compares by a factor of 3.
2025-07-02 04:52:32.142 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.142 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.142 # of the computation is cached by cruncher
2025-07-02 04:52:32.142 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.142 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.142 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.142 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.142 if best_ratio < cutoff:
2025-07-02 04:52:32.142 # no non-identical "pretty close" pair
2025-07-02 04:52:32.142 if eqi is None:
2025-07-02 04:52:32.142 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.142 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.142 return
2025-07-02 04:52:32.142 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.142 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.142 else:
2025-07-02 04:52:32.143 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.143 eqi = None
2025-07-02 04:52:32.143
2025-07-02 04:52:32.143 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.143 # identical
2025-07-02 04:52:32.143
2025-07-02 04:52:32.143 # pump out diffs from before the synch point
2025-07-02 04:52:32.143 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.143
2025-07-02 04:52:32.143 # do intraline marking on the synch pair
2025-07-02 04:52:32.143 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.143 if eqi is None:
2025-07-02 04:52:32.143 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.143 atags = btags = ""
2025-07-02 04:52:32.143 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.143 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.143 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.143 if tag == 'replace':
2025-07-02 04:52:32.144 atags += '^' * la
2025-07-02 04:52:32.144 btags += '^' * lb
2025-07-02 04:52:32.144 elif tag == 'delete':
2025-07-02 04:52:32.144 atags += '-' * la
2025-07-02 04:52:32.144 elif tag == 'insert':
2025-07-02 04:52:32.144 btags += '+' * lb
2025-07-02 04:52:32.144 elif tag == 'equal':
2025-07-02 04:52:32.144 atags += ' ' * la
2025-07-02 04:52:32.144 btags += ' ' * lb
2025-07-02 04:52:32.144 else:
2025-07-02 04:52:32.144 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.144 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.144 else:
2025-07-02 04:52:32.144 # the synch pair is identical
2025-07-02 04:52:32.144 yield ' ' + aelt
2025-07-02 04:52:32.144
2025-07-02 04:52:32.144 # pump out diffs from after the synch point
2025-07-02 04:52:32.144 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.144
2025-07-02 04:52:32.144 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.144 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.145
2025-07-02 04:52:32.145 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.145 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.145 alo = 172, ahi = 1101
2025-07-02 04:52:32.145 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.145 blo = 172, bhi = 1101
2025-07-02 04:52:32.145
2025-07-02 04:52:32.145 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.145 g = []
2025-07-02 04:52:32.145 if alo < ahi:
2025-07-02 04:52:32.145 if blo < bhi:
2025-07-02 04:52:32.145 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.145 else:
2025-07-02 04:52:32.145 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.145 elif blo < bhi:
2025-07-02 04:52:32.145 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.145
2025-07-02 04:52:32.145 > yield from g
2025-07-02 04:52:32.145
2025-07-02 04:52:32.145 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.146 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.146
2025-07-02 04:52:32.146 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.146 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.146 alo = 172, ahi = 1101
2025-07-02 04:52:32.146 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.146 blo = 172, bhi = 1101
2025-07-02 04:52:32.146
2025-07-02 04:52:32.146 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.146 r"""
2025-07-02 04:52:32.146 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.146 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.146 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.146 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.146
2025-07-02 04:52:32.146 Example:
2025-07-02 04:52:32.146
2025-07-02 04:52:32.146 >>> d = Differ()
2025-07-02 04:52:32.146 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.146 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.146 >>> print(''.join(results), end="")
2025-07-02 04:52:32.147 - abcDefghiJkl
2025-07-02 04:52:32.147 + abcdefGhijkl
2025-07-02 04:52:32.147 """
2025-07-02 04:52:32.147
2025-07-02 04:52:32.147 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.147 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.147 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.147 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.147 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.147
2025-07-02 04:52:32.147 # search for the pair that matches best without being identical
2025-07-02 04:52:32.147 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.147 # on junk -- unless we have to)
2025-07-02 04:52:32.147 for j in range(blo, bhi):
2025-07-02 04:52:32.147 bj = b[j]
2025-07-02 04:52:32.147 cruncher.set_seq2(bj)
2025-07-02 04:52:32.147 for i in range(alo, ahi):
2025-07-02 04:52:32.147 ai = a[i]
2025-07-02 04:52:32.147 if ai == bj:
2025-07-02 04:52:32.148 if eqi is None:
2025-07-02 04:52:32.148 eqi, eqj = i, j
2025-07-02 04:52:32.148 continue
2025-07-02 04:52:32.148 cruncher.set_seq1(ai)
2025-07-02 04:52:32.148 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.148 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.148 # compares by a factor of 3.
2025-07-02 04:52:32.148 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.148 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.148 # of the computation is cached by cruncher
2025-07-02 04:52:32.148 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.148 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.148 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.148 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.148 if best_ratio < cutoff:
2025-07-02 04:52:32.148 # no non-identical "pretty close" pair
2025-07-02 04:52:32.148 if eqi is None:
2025-07-02 04:52:32.148 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.148 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.148 return
2025-07-02 04:52:32.149 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.149 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.149 else:
2025-07-02 04:52:32.149 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.149 eqi = None
2025-07-02 04:52:32.149
2025-07-02 04:52:32.149 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.149 # identical
2025-07-02 04:52:32.149
2025-07-02 04:52:32.149 # pump out diffs from before the synch point
2025-07-02 04:52:32.149 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.149
2025-07-02 04:52:32.149 # do intraline marking on the synch pair
2025-07-02 04:52:32.149 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.149 if eqi is None:
2025-07-02 04:52:32.149 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.149 atags = btags = ""
2025-07-02 04:52:32.149 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.149 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.150 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.150 if tag == 'replace':
2025-07-02 04:52:32.150 atags += '^' * la
2025-07-02 04:52:32.150 btags += '^' * lb
2025-07-02 04:52:32.150 elif tag == 'delete':
2025-07-02 04:52:32.150 atags += '-' * la
2025-07-02 04:52:32.150 elif tag == 'insert':
2025-07-02 04:52:32.150 btags += '+' * lb
2025-07-02 04:52:32.150 elif tag == 'equal':
2025-07-02 04:52:32.150 atags += ' ' * la
2025-07-02 04:52:32.150 btags += ' ' * lb
2025-07-02 04:52:32.150 else:
2025-07-02 04:52:32.150 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.150 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.150 else:
2025-07-02 04:52:32.150 # the synch pair is identical
2025-07-02 04:52:32.150 yield ' ' + aelt
2025-07-02 04:52:32.150
2025-07-02 04:52:32.150 # pump out diffs from after the synch point
2025-07-02 04:52:32.150 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.151
2025-07-02 04:52:32.151 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.151 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.151
2025-07-02 04:52:32.151 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.151 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.151 alo = 173, ahi = 1101
2025-07-02 04:52:32.151 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.151 blo = 173, bhi = 1101
2025-07-02 04:52:32.151
2025-07-02 04:52:32.151 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.151 g = []
2025-07-02 04:52:32.151 if alo < ahi:
2025-07-02 04:52:32.151 if blo < bhi:
2025-07-02 04:52:32.151 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.151 else:
2025-07-02 04:52:32.151 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.151 elif blo < bhi:
2025-07-02 04:52:32.151 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.152
2025-07-02 04:52:32.152 > yield from g
2025-07-02 04:52:32.152
2025-07-02 04:52:32.152 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.152 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.152
2025-07-02 04:52:32.152 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.152 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.152 alo = 173, ahi = 1101
2025-07-02 04:52:32.152 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.152 blo = 173, bhi = 1101
2025-07-02 04:52:32.152
2025-07-02 04:52:32.152 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.152 r"""
2025-07-02 04:52:32.152 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.152 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.152 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.152 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.152
2025-07-02 04:52:32.153 Example:
2025-07-02 04:52:32.153
2025-07-02 04:52:32.153 >>> d = Differ()
2025-07-02 04:52:32.153 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.153 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.153 >>> print(''.join(results), end="")
2025-07-02 04:52:32.153 - abcDefghiJkl
2025-07-02 04:52:32.153 + abcdefGhijkl
2025-07-02 04:52:32.153 """
2025-07-02 04:52:32.153
2025-07-02 04:52:32.153 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.153 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.153 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.153 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.153 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.153
2025-07-02 04:52:32.153 # search for the pair that matches best without being identical
2025-07-02 04:52:32.153 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.154 # on junk -- unless we have to)
2025-07-02 04:52:32.154 for j in range(blo, bhi):
2025-07-02 04:52:32.154 bj = b[j]
2025-07-02 04:52:32.154 cruncher.set_seq2(bj)
2025-07-02 04:52:32.154 for i in range(alo, ahi):
2025-07-02 04:52:32.154 ai = a[i]
2025-07-02 04:52:32.154 if ai == bj:
2025-07-02 04:52:32.154 if eqi is None:
2025-07-02 04:52:32.154 eqi, eqj = i, j
2025-07-02 04:52:32.154 continue
2025-07-02 04:52:32.154 cruncher.set_seq1(ai)
2025-07-02 04:52:32.154 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.154 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.154 # compares by a factor of 3.
2025-07-02 04:52:32.154 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.154 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.154 # of the computation is cached by cruncher
2025-07-02 04:52:32.154 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.154 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.154 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.155 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.155 if best_ratio < cutoff:
2025-07-02 04:52:32.155 # no non-identical "pretty close" pair
2025-07-02 04:52:32.155 if eqi is None:
2025-07-02 04:52:32.155 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.155 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.155 return
2025-07-02 04:52:32.155 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.155 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.155 else:
2025-07-02 04:52:32.155 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.155 eqi = None
2025-07-02 04:52:32.155
2025-07-02 04:52:32.155 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.155 # identical
2025-07-02 04:52:32.155
2025-07-02 04:52:32.155 # pump out diffs from before the synch point
2025-07-02 04:52:32.155 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.155
2025-07-02 04:52:32.155 # do intraline marking on the synch pair
2025-07-02 04:52:32.155 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.155 if eqi is None:
2025-07-02 04:52:32.156 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.156 atags = btags = ""
2025-07-02 04:52:32.156 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.156 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.156 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.156 if tag == 'replace':
2025-07-02 04:52:32.156 atags += '^' * la
2025-07-02 04:52:32.156 btags += '^' * lb
2025-07-02 04:52:32.156 elif tag == 'delete':
2025-07-02 04:52:32.156 atags += '-' * la
2025-07-02 04:52:32.156 elif tag == 'insert':
2025-07-02 04:52:32.156 btags += '+' * lb
2025-07-02 04:52:32.156 elif tag == 'equal':
2025-07-02 04:52:32.156 atags += ' ' * la
2025-07-02 04:52:32.156 btags += ' ' * lb
2025-07-02 04:52:32.156 else:
2025-07-02 04:52:32.156 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.156 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.156 else:
2025-07-02 04:52:32.156 # the synch pair is identical
2025-07-02 04:52:32.156 yield ' ' + aelt
2025-07-02 04:52:32.157
2025-07-02 04:52:32.157 # pump out diffs from after the synch point
2025-07-02 04:52:32.157 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.157
2025-07-02 04:52:32.157 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.157 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.157
2025-07-02 04:52:32.157 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.157 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.157 alo = 174, ahi = 1101
2025-07-02 04:52:32.157 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.157 blo = 174, bhi = 1101
2025-07-02 04:52:32.157
2025-07-02 04:52:32.157 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.157 g = []
2025-07-02 04:52:32.157 if alo < ahi:
2025-07-02 04:52:32.157 if blo < bhi:
2025-07-02 04:52:32.157 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.157 else:
2025-07-02 04:52:32.157 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.157 elif blo < bhi:
2025-07-02 04:52:32.158 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.158
2025-07-02 04:52:32.158 > yield from g
2025-07-02 04:52:32.158
2025-07-02 04:52:32.158 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.158 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.158
2025-07-02 04:52:32.158 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.158 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.158 alo = 174, ahi = 1101
2025-07-02 04:52:32.158 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.158 blo = 174, bhi = 1101
2025-07-02 04:52:32.158
2025-07-02 04:52:32.158 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.158 r"""
2025-07-02 04:52:32.158 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.158 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.158 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.158 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.158
2025-07-02 04:52:32.158 Example:
2025-07-02 04:52:32.158
2025-07-02 04:52:32.159 >>> d = Differ()
2025-07-02 04:52:32.159 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.159 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.159 >>> print(''.join(results), end="")
2025-07-02 04:52:32.159 - abcDefghiJkl
2025-07-02 04:52:32.159 + abcdefGhijkl
2025-07-02 04:52:32.159 """
2025-07-02 04:52:32.159
2025-07-02 04:52:32.159 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.159 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.159 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.159 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.159 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.159
2025-07-02 04:52:32.159 # search for the pair that matches best without being identical
2025-07-02 04:52:32.159 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.159 # on junk -- unless we have to)
2025-07-02 04:52:32.159 for j in range(blo, bhi):
2025-07-02 04:52:32.159 bj = b[j]
2025-07-02 04:52:32.160 cruncher.set_seq2(bj)
2025-07-02 04:52:32.160 for i in range(alo, ahi):
2025-07-02 04:52:32.160 ai = a[i]
2025-07-02 04:52:32.160 if ai == bj:
2025-07-02 04:52:32.160 if eqi is None:
2025-07-02 04:52:32.160 eqi, eqj = i, j
2025-07-02 04:52:32.160 continue
2025-07-02 04:52:32.160 cruncher.set_seq1(ai)
2025-07-02 04:52:32.160 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.160 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.160 # compares by a factor of 3.
2025-07-02 04:52:32.160 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.160 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.160 # of the computation is cached by cruncher
2025-07-02 04:52:32.160 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.160 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.160 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.160 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.160 if best_ratio < cutoff:
2025-07-02 04:52:32.160 # no non-identical "pretty close" pair
2025-07-02 04:52:32.161 if eqi is None:
2025-07-02 04:52:32.161 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.161 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.161 return
2025-07-02 04:52:32.161 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.161 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.161 else:
2025-07-02 04:52:32.161 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.161 eqi = None
2025-07-02 04:52:32.161
2025-07-02 04:52:32.161 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.161 # identical
2025-07-02 04:52:32.161
2025-07-02 04:52:32.161 # pump out diffs from before the synch point
2025-07-02 04:52:32.161 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.161
2025-07-02 04:52:32.161 # do intraline marking on the synch pair
2025-07-02 04:52:32.161 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.161 if eqi is None:
2025-07-02 04:52:32.161 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.162 atags = btags = ""
2025-07-02 04:52:32.162 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.162 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.162 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.162 if tag == 'replace':
2025-07-02 04:52:32.162 atags += '^' * la
2025-07-02 04:52:32.162 btags += '^' * lb
2025-07-02 04:52:32.162 elif tag == 'delete':
2025-07-02 04:52:32.162 atags += '-' * la
2025-07-02 04:52:32.162 elif tag == 'insert':
2025-07-02 04:52:32.162 btags += '+' * lb
2025-07-02 04:52:32.162 elif tag == 'equal':
2025-07-02 04:52:32.162 atags += ' ' * la
2025-07-02 04:52:32.162 btags += ' ' * lb
2025-07-02 04:52:32.162 else:
2025-07-02 04:52:32.162 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.162 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.162 else:
2025-07-02 04:52:32.162 # the synch pair is identical
2025-07-02 04:52:32.162 yield ' ' + aelt
2025-07-02 04:52:32.162
2025-07-02 04:52:32.162 # pump out diffs from after the synch point
2025-07-02 04:52:32.163 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.163
2025-07-02 04:52:32.163 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.163 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.163
2025-07-02 04:52:32.163 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.163 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.163 alo = 175, ahi = 1101
2025-07-02 04:52:32.163 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.163 blo = 175, bhi = 1101
2025-07-02 04:52:32.163
2025-07-02 04:52:32.163 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.163 g = []
2025-07-02 04:52:32.163 if alo < ahi:
2025-07-02 04:52:32.163 if blo < bhi:
2025-07-02 04:52:32.163 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.163 else:
2025-07-02 04:52:32.163 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.163 elif blo < bhi:
2025-07-02 04:52:32.163 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.163
2025-07-02 04:52:32.164 > yield from g
2025-07-02 04:52:32.164
2025-07-02 04:52:32.164 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.164 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.164
2025-07-02 04:52:32.164 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.164 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.164 alo = 175, ahi = 1101
2025-07-02 04:52:32.164 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.164 blo = 175, bhi = 1101
2025-07-02 04:52:32.164
2025-07-02 04:52:32.164 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.164 r"""
2025-07-02 04:52:32.164 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.164 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.164 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.164 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.164
2025-07-02 04:52:32.164 Example:
2025-07-02 04:52:32.164
2025-07-02 04:52:32.165 >>> d = Differ()
2025-07-02 04:52:32.165 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.165 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.165 >>> print(''.join(results), end="")
2025-07-02 04:52:32.165 - abcDefghiJkl
2025-07-02 04:52:32.165 + abcdefGhijkl
2025-07-02 04:52:32.165 """
2025-07-02 04:52:32.165
2025-07-02 04:52:32.165 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.165 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.165 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.165 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.165 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.165
2025-07-02 04:52:32.165 # search for the pair that matches best without being identical
2025-07-02 04:52:32.165 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.165 # on junk -- unless we have to)
2025-07-02 04:52:32.165 for j in range(blo, bhi):
2025-07-02 04:52:32.165 bj = b[j]
2025-07-02 04:52:32.166 cruncher.set_seq2(bj)
2025-07-02 04:52:32.166 for i in range(alo, ahi):
2025-07-02 04:52:32.166 ai = a[i]
2025-07-02 04:52:32.166 if ai == bj:
2025-07-02 04:52:32.166 if eqi is None:
2025-07-02 04:52:32.166 eqi, eqj = i, j
2025-07-02 04:52:32.166 continue
2025-07-02 04:52:32.166 cruncher.set_seq1(ai)
2025-07-02 04:52:32.166 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.166 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.166 # compares by a factor of 3.
2025-07-02 04:52:32.166 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.166 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.166 # of the computation is cached by cruncher
2025-07-02 04:52:32.166 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.166 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.166 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.166 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.166 if best_ratio < cutoff:
2025-07-02 04:52:32.166 # no non-identical "pretty close" pair
2025-07-02 04:52:32.167 if eqi is None:
2025-07-02 04:52:32.167 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.167 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.167 return
2025-07-02 04:52:32.167 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.167 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.167 else:
2025-07-02 04:52:32.167 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.167 eqi = None
2025-07-02 04:52:32.167
2025-07-02 04:52:32.167 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.167 # identical
2025-07-02 04:52:32.167
2025-07-02 04:52:32.167 # pump out diffs from before the synch point
2025-07-02 04:52:32.167 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.167
2025-07-02 04:52:32.167 # do intraline marking on the synch pair
2025-07-02 04:52:32.167 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.167 if eqi is None:
2025-07-02 04:52:32.167 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.167 atags = btags = ""
2025-07-02 04:52:32.168 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.168 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.168 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.168 if tag == 'replace':
2025-07-02 04:52:32.168 atags += '^' * la
2025-07-02 04:52:32.168 btags += '^' * lb
2025-07-02 04:52:32.168 elif tag == 'delete':
2025-07-02 04:52:32.168 atags += '-' * la
2025-07-02 04:52:32.168 elif tag == 'insert':
2025-07-02 04:52:32.168 btags += '+' * lb
2025-07-02 04:52:32.168 elif tag == 'equal':
2025-07-02 04:52:32.168 atags += ' ' * la
2025-07-02 04:52:32.168 btags += ' ' * lb
2025-07-02 04:52:32.168 else:
2025-07-02 04:52:32.168 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.168 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.168 else:
2025-07-02 04:52:32.168 # the synch pair is identical
2025-07-02 04:52:32.168 yield ' ' + aelt
2025-07-02 04:52:32.168
2025-07-02 04:52:32.169 # pump out diffs from after the synch point
2025-07-02 04:52:32.169 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.169
2025-07-02 04:52:32.169 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.169 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.169
2025-07-02 04:52:32.169 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.169 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.169 alo = 176, ahi = 1101
2025-07-02 04:52:32.169 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.169 blo = 176, bhi = 1101
2025-07-02 04:52:32.169
2025-07-02 04:52:32.169 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.169 g = []
2025-07-02 04:52:32.169 if alo < ahi:
2025-07-02 04:52:32.169 if blo < bhi:
2025-07-02 04:52:32.169 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.169 else:
2025-07-02 04:52:32.169 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.169 elif blo < bhi:
2025-07-02 04:52:32.170 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.170
2025-07-02 04:52:32.170 > yield from g
2025-07-02 04:52:32.170
2025-07-02 04:52:32.170 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.170 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.170
2025-07-02 04:52:32.170 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.170 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.170 alo = 176, ahi = 1101
2025-07-02 04:52:32.170 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.170 blo = 176, bhi = 1101
2025-07-02 04:52:32.170
2025-07-02 04:52:32.170 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.170 r"""
2025-07-02 04:52:32.170 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.170 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.170 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.170 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.170
2025-07-02 04:52:32.170 Example:
2025-07-02 04:52:32.171
2025-07-02 04:52:32.171 >>> d = Differ()
2025-07-02 04:52:32.171 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.171 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.171 >>> print(''.join(results), end="")
2025-07-02 04:52:32.171 - abcDefghiJkl
2025-07-02 04:52:32.171 + abcdefGhijkl
2025-07-02 04:52:32.171 """
2025-07-02 04:52:32.171
2025-07-02 04:52:32.171 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.171 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.171 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.171 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.171 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.171
2025-07-02 04:52:32.171 # search for the pair that matches best without being identical
2025-07-02 04:52:32.171 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.171 # on junk -- unless we have to)
2025-07-02 04:52:32.171 for j in range(blo, bhi):
2025-07-02 04:52:32.172 bj = b[j]
2025-07-02 04:52:32.172 cruncher.set_seq2(bj)
2025-07-02 04:52:32.172 for i in range(alo, ahi):
2025-07-02 04:52:32.172 ai = a[i]
2025-07-02 04:52:32.172 if ai == bj:
2025-07-02 04:52:32.172 if eqi is None:
2025-07-02 04:52:32.172 eqi, eqj = i, j
2025-07-02 04:52:32.172 continue
2025-07-02 04:52:32.172 cruncher.set_seq1(ai)
2025-07-02 04:52:32.172 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.172 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.172 # compares by a factor of 3.
2025-07-02 04:52:32.172 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.172 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.172 # of the computation is cached by cruncher
2025-07-02 04:52:32.172 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.172 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.172 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.172 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.172 if best_ratio < cutoff:
2025-07-02 04:52:32.172 # no non-identical "pretty close" pair
2025-07-02 04:52:32.172 if eqi is None:
2025-07-02 04:52:32.173 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.173 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.173 return
2025-07-02 04:52:32.173 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.173 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.173 else:
2025-07-02 04:52:32.173 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.173 eqi = None
2025-07-02 04:52:32.173
2025-07-02 04:52:32.173 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.173 # identical
2025-07-02 04:52:32.173
2025-07-02 04:52:32.173 # pump out diffs from before the synch point
2025-07-02 04:52:32.173 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.173
2025-07-02 04:52:32.173 # do intraline marking on the synch pair
2025-07-02 04:52:32.173 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.173 if eqi is None:
2025-07-02 04:52:32.173 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.173 atags = btags = ""
2025-07-02 04:52:32.173 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.174 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.174 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.174 if tag == 'replace':
2025-07-02 04:52:32.174 atags += '^' * la
2025-07-02 04:52:32.174 btags += '^' * lb
2025-07-02 04:52:32.174 elif tag == 'delete':
2025-07-02 04:52:32.174 atags += '-' * la
2025-07-02 04:52:32.174 elif tag == 'insert':
2025-07-02 04:52:32.174 btags += '+' * lb
2025-07-02 04:52:32.174 elif tag == 'equal':
2025-07-02 04:52:32.174 atags += ' ' * la
2025-07-02 04:52:32.174 btags += ' ' * lb
2025-07-02 04:52:32.174 else:
2025-07-02 04:52:32.174 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.174 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.174 else:
2025-07-02 04:52:32.174 # the synch pair is identical
2025-07-02 04:52:32.174 yield ' ' + aelt
2025-07-02 04:52:32.174
2025-07-02 04:52:32.174 # pump out diffs from after the synch point
2025-07-02 04:52:32.174 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.174
2025-07-02 04:52:32.175 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.175 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.175
2025-07-02 04:52:32.175 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.175 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.175 alo = 177, ahi = 1101
2025-07-02 04:52:32.175 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.175 blo = 177, bhi = 1101
2025-07-02 04:52:32.175
2025-07-02 04:52:32.175 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.175 g = []
2025-07-02 04:52:32.175 if alo < ahi:
2025-07-02 04:52:32.175 if blo < bhi:
2025-07-02 04:52:32.175 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.175 else:
2025-07-02 04:52:32.175 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.175 elif blo < bhi:
2025-07-02 04:52:32.175 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.175
2025-07-02 04:52:32.175 > yield from g
2025-07-02 04:52:32.175
2025-07-02 04:52:32.176 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.176 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.176
2025-07-02 04:52:32.176 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.176 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.176 alo = 177, ahi = 1101
2025-07-02 04:52:32.176 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.176 blo = 177, bhi = 1101
2025-07-02 04:52:32.176
2025-07-02 04:52:32.176 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.176 r"""
2025-07-02 04:52:32.176 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.176 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.176 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.176 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.176
2025-07-02 04:52:32.176 Example:
2025-07-02 04:52:32.176
2025-07-02 04:52:32.176 >>> d = Differ()
2025-07-02 04:52:32.176 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.177 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.177 >>> print(''.join(results), end="")
2025-07-02 04:52:32.177 - abcDefghiJkl
2025-07-02 04:52:32.177 + abcdefGhijkl
2025-07-02 04:52:32.177 """
2025-07-02 04:52:32.177
2025-07-02 04:52:32.177 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.177 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.177 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.177 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.177 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.177
2025-07-02 04:52:32.177 # search for the pair that matches best without being identical
2025-07-02 04:52:32.177 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.177 # on junk -- unless we have to)
2025-07-02 04:52:32.177 for j in range(blo, bhi):
2025-07-02 04:52:32.177 bj = b[j]
2025-07-02 04:52:32.177 cruncher.set_seq2(bj)
2025-07-02 04:52:32.177 for i in range(alo, ahi):
2025-07-02 04:52:32.178 ai = a[i]
2025-07-02 04:52:32.178 if ai == bj:
2025-07-02 04:52:32.178 if eqi is None:
2025-07-02 04:52:32.178 eqi, eqj = i, j
2025-07-02 04:52:32.178 continue
2025-07-02 04:52:32.178 cruncher.set_seq1(ai)
2025-07-02 04:52:32.178 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.178 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.178 # compares by a factor of 3.
2025-07-02 04:52:32.178 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.178 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.178 # of the computation is cached by cruncher
2025-07-02 04:52:32.178 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.178 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.178 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.178 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.178 if best_ratio < cutoff:
2025-07-02 04:52:32.178 # no non-identical "pretty close" pair
2025-07-02 04:52:32.178 if eqi is None:
2025-07-02 04:52:32.178 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.178 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.179 return
2025-07-02 04:52:32.179 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.179 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.179 else:
2025-07-02 04:52:32.179 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.179 eqi = None
2025-07-02 04:52:32.179
2025-07-02 04:52:32.179 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.179 # identical
2025-07-02 04:52:32.179
2025-07-02 04:52:32.179 # pump out diffs from before the synch point
2025-07-02 04:52:32.179 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.179
2025-07-02 04:52:32.179 # do intraline marking on the synch pair
2025-07-02 04:52:32.179 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.179 if eqi is None:
2025-07-02 04:52:32.179 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.179 atags = btags = ""
2025-07-02 04:52:32.179 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.179 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.179 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.180 if tag == 'replace':
2025-07-02 04:52:32.180 atags += '^' * la
2025-07-02 04:52:32.180 btags += '^' * lb
2025-07-02 04:52:32.180 elif tag == 'delete':
2025-07-02 04:52:32.180 atags += '-' * la
2025-07-02 04:52:32.180 elif tag == 'insert':
2025-07-02 04:52:32.180 btags += '+' * lb
2025-07-02 04:52:32.180 elif tag == 'equal':
2025-07-02 04:52:32.180 atags += ' ' * la
2025-07-02 04:52:32.180 btags += ' ' * lb
2025-07-02 04:52:32.180 else:
2025-07-02 04:52:32.180 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.180 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.180 else:
2025-07-02 04:52:32.180 # the synch pair is identical
2025-07-02 04:52:32.180 yield ' ' + aelt
2025-07-02 04:52:32.180
2025-07-02 04:52:32.180 # pump out diffs from after the synch point
2025-07-02 04:52:32.180 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.180
2025-07-02 04:52:32.180 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.180 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.181
2025-07-02 04:52:32.181 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.181 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.181 alo = 180, ahi = 1101
2025-07-02 04:52:32.181 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.181 blo = 180, bhi = 1101
2025-07-02 04:52:32.181
2025-07-02 04:52:32.181 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.181 g = []
2025-07-02 04:52:32.181 if alo < ahi:
2025-07-02 04:52:32.181 if blo < bhi:
2025-07-02 04:52:32.181 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.181 else:
2025-07-02 04:52:32.181 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.181 elif blo < bhi:
2025-07-02 04:52:32.181 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.181
2025-07-02 04:52:32.181 > yield from g
2025-07-02 04:52:32.181
2025-07-02 04:52:32.181 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.181 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.182
2025-07-02 04:52:32.182 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.182 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.182 alo = 180, ahi = 1101
2025-07-02 04:52:32.182 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.182 blo = 180, bhi = 1101
2025-07-02 04:52:32.182
2025-07-02 04:52:32.182 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.182 r"""
2025-07-02 04:52:32.182 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.182 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.182 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.182 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.182
2025-07-02 04:52:32.182 Example:
2025-07-02 04:52:32.182
2025-07-02 04:52:32.182 >>> d = Differ()
2025-07-02 04:52:32.182 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.182 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.183 >>> print(''.join(results), end="")
2025-07-02 04:52:32.183 - abcDefghiJkl
2025-07-02 04:52:32.183 + abcdefGhijkl
2025-07-02 04:52:32.183 """
2025-07-02 04:52:32.183
2025-07-02 04:52:32.183 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.183 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.183 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.183 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.183 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.183
2025-07-02 04:52:32.183 # search for the pair that matches best without being identical
2025-07-02 04:52:32.183 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.183 # on junk -- unless we have to)
2025-07-02 04:52:32.183 for j in range(blo, bhi):
2025-07-02 04:52:32.183 bj = b[j]
2025-07-02 04:52:32.183 cruncher.set_seq2(bj)
2025-07-02 04:52:32.183 for i in range(alo, ahi):
2025-07-02 04:52:32.183 ai = a[i]
2025-07-02 04:52:32.184 if ai == bj:
2025-07-02 04:52:32.184 if eqi is None:
2025-07-02 04:52:32.184 eqi, eqj = i, j
2025-07-02 04:52:32.184 continue
2025-07-02 04:52:32.184 cruncher.set_seq1(ai)
2025-07-02 04:52:32.184 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.184 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.184 # compares by a factor of 3.
2025-07-02 04:52:32.184 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.184 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.184 # of the computation is cached by cruncher
2025-07-02 04:52:32.184 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.184 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.184 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.184 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.184 if best_ratio < cutoff:
2025-07-02 04:52:32.184 # no non-identical "pretty close" pair
2025-07-02 04:52:32.184 if eqi is None:
2025-07-02 04:52:32.184 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.184 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.185 return
2025-07-02 04:52:32.185 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.185 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.185 else:
2025-07-02 04:52:32.185 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.185 eqi = None
2025-07-02 04:52:32.185
2025-07-02 04:52:32.185 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.185 # identical
2025-07-02 04:52:32.185
2025-07-02 04:52:32.185 # pump out diffs from before the synch point
2025-07-02 04:52:32.185 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.185
2025-07-02 04:52:32.185 # do intraline marking on the synch pair
2025-07-02 04:52:32.185 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.185 if eqi is None:
2025-07-02 04:52:32.185 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.185 atags = btags = ""
2025-07-02 04:52:32.185 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.185 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.185 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.186 if tag == 'replace':
2025-07-02 04:52:32.186 atags += '^' * la
2025-07-02 04:52:32.186 btags += '^' * lb
2025-07-02 04:52:32.186 elif tag == 'delete':
2025-07-02 04:52:32.186 atags += '-' * la
2025-07-02 04:52:32.186 elif tag == 'insert':
2025-07-02 04:52:32.186 btags += '+' * lb
2025-07-02 04:52:32.186 elif tag == 'equal':
2025-07-02 04:52:32.186 atags += ' ' * la
2025-07-02 04:52:32.186 btags += ' ' * lb
2025-07-02 04:52:32.186 else:
2025-07-02 04:52:32.186 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.186 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.186 else:
2025-07-02 04:52:32.186 # the synch pair is identical
2025-07-02 04:52:32.186 yield ' ' + aelt
2025-07-02 04:52:32.186
2025-07-02 04:52:32.186 # pump out diffs from after the synch point
2025-07-02 04:52:32.186 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.186
2025-07-02 04:52:32.186 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.187 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.187
2025-07-02 04:52:32.187 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.187 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.187 alo = 181, ahi = 1101
2025-07-02 04:52:32.187 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.187 blo = 181, bhi = 1101
2025-07-02 04:52:32.187
2025-07-02 04:52:32.187 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.187 g = []
2025-07-02 04:52:32.187 if alo < ahi:
2025-07-02 04:52:32.187 if blo < bhi:
2025-07-02 04:52:32.187 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.187 else:
2025-07-02 04:52:32.187 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.187 elif blo < bhi:
2025-07-02 04:52:32.187 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.187
2025-07-02 04:52:32.187 > yield from g
2025-07-02 04:52:32.187
2025-07-02 04:52:32.187 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.188 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.188
2025-07-02 04:52:32.188 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.188 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.188 alo = 181, ahi = 1101
2025-07-02 04:52:32.188 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.188 blo = 181, bhi = 1101
2025-07-02 04:52:32.188
2025-07-02 04:52:32.188 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.188 r"""
2025-07-02 04:52:32.188 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.188 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.188 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.188 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.188
2025-07-02 04:52:32.188 Example:
2025-07-02 04:52:32.188
2025-07-02 04:52:32.188 >>> d = Differ()
2025-07-02 04:52:32.188 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.188 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.188 >>> print(''.join(results), end="")
2025-07-02 04:52:32.189 - abcDefghiJkl
2025-07-02 04:52:32.189 + abcdefGhijkl
2025-07-02 04:52:32.189 """
2025-07-02 04:52:32.189
2025-07-02 04:52:32.189 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.189 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.189 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.189 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.189 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.189
2025-07-02 04:52:32.189 # search for the pair that matches best without being identical
2025-07-02 04:52:32.189 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.189 # on junk -- unless we have to)
2025-07-02 04:52:32.189 for j in range(blo, bhi):
2025-07-02 04:52:32.189 bj = b[j]
2025-07-02 04:52:32.189 cruncher.set_seq2(bj)
2025-07-02 04:52:32.189 for i in range(alo, ahi):
2025-07-02 04:52:32.189 ai = a[i]
2025-07-02 04:52:32.189 if ai == bj:
2025-07-02 04:52:32.189 if eqi is None:
2025-07-02 04:52:32.190 eqi, eqj = i, j
2025-07-02 04:52:32.190 continue
2025-07-02 04:52:32.190 cruncher.set_seq1(ai)
2025-07-02 04:52:32.190 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.190 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.190 # compares by a factor of 3.
2025-07-02 04:52:32.190 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.190 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.190 # of the computation is cached by cruncher
2025-07-02 04:52:32.190 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.190 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.190 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.190 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.190 if best_ratio < cutoff:
2025-07-02 04:52:32.190 # no non-identical "pretty close" pair
2025-07-02 04:52:32.190 if eqi is None:
2025-07-02 04:52:32.190 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.190 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.190 return
2025-07-02 04:52:32.190 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.190 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.191 else:
2025-07-02 04:52:32.191 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.191 eqi = None
2025-07-02 04:52:32.191
2025-07-02 04:52:32.191 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.191 # identical
2025-07-02 04:52:32.191
2025-07-02 04:52:32.191 # pump out diffs from before the synch point
2025-07-02 04:52:32.191 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.191
2025-07-02 04:52:32.191 # do intraline marking on the synch pair
2025-07-02 04:52:32.191 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.191 if eqi is None:
2025-07-02 04:52:32.191 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.191 atags = btags = ""
2025-07-02 04:52:32.191 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.191 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.191 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.191 if tag == 'replace':
2025-07-02 04:52:32.191 atags += '^' * la
2025-07-02 04:52:32.191 btags += '^' * lb
2025-07-02 04:52:32.191 elif tag == 'delete':
2025-07-02 04:52:32.192 atags += '-' * la
2025-07-02 04:52:32.192 elif tag == 'insert':
2025-07-02 04:52:32.192 btags += '+' * lb
2025-07-02 04:52:32.192 elif tag == 'equal':
2025-07-02 04:52:32.192 atags += ' ' * la
2025-07-02 04:52:32.192 btags += ' ' * lb
2025-07-02 04:52:32.192 else:
2025-07-02 04:52:32.192 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.192 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.192 else:
2025-07-02 04:52:32.192 # the synch pair is identical
2025-07-02 04:52:32.192 yield ' ' + aelt
2025-07-02 04:52:32.192
2025-07-02 04:52:32.192 # pump out diffs from after the synch point
2025-07-02 04:52:32.192 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.192
2025-07-02 04:52:32.192 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.192 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.192
2025-07-02 04:52:32.192 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.192 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.193 alo = 182, ahi = 1101
2025-07-02 04:52:32.193 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.193 blo = 182, bhi = 1101
2025-07-02 04:52:32.193
2025-07-02 04:52:32.193 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.193 g = []
2025-07-02 04:52:32.193 if alo < ahi:
2025-07-02 04:52:32.193 if blo < bhi:
2025-07-02 04:52:32.193 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.193 else:
2025-07-02 04:52:32.193 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.193 elif blo < bhi:
2025-07-02 04:52:32.193 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.193
2025-07-02 04:52:32.193 > yield from g
2025-07-02 04:52:32.193
2025-07-02 04:52:32.193 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.193 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.193
2025-07-02 04:52:32.193 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.194 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.194 alo = 182, ahi = 1101
2025-07-02 04:52:32.194 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.194 blo = 182, bhi = 1101
2025-07-02 04:52:32.194
2025-07-02 04:52:32.194 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.194 r"""
2025-07-02 04:52:32.194 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.194 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.194 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.194 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.194
2025-07-02 04:52:32.194 Example:
2025-07-02 04:52:32.194
2025-07-02 04:52:32.194 >>> d = Differ()
2025-07-02 04:52:32.194 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.194 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.194 >>> print(''.join(results), end="")
2025-07-02 04:52:32.194 - abcDefghiJkl
2025-07-02 04:52:32.195 + abcdefGhijkl
2025-07-02 04:52:32.195 """
2025-07-02 04:52:32.195
2025-07-02 04:52:32.195 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.195 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.195 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.195 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.195 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.195
2025-07-02 04:52:32.195 # search for the pair that matches best without being identical
2025-07-02 04:52:32.195 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.195 # on junk -- unless we have to)
2025-07-02 04:52:32.195 for j in range(blo, bhi):
2025-07-02 04:52:32.195 bj = b[j]
2025-07-02 04:52:32.195 cruncher.set_seq2(bj)
2025-07-02 04:52:32.195 for i in range(alo, ahi):
2025-07-02 04:52:32.195 ai = a[i]
2025-07-02 04:52:32.195 if ai == bj:
2025-07-02 04:52:32.195 if eqi is None:
2025-07-02 04:52:32.195 eqi, eqj = i, j
2025-07-02 04:52:32.195 continue
2025-07-02 04:52:32.196 cruncher.set_seq1(ai)
2025-07-02 04:52:32.196 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.196 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.196 # compares by a factor of 3.
2025-07-02 04:52:32.196 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.196 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.196 # of the computation is cached by cruncher
2025-07-02 04:52:32.196 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.196 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.196 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.196 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.196 if best_ratio < cutoff:
2025-07-02 04:52:32.196 # no non-identical "pretty close" pair
2025-07-02 04:52:32.196 if eqi is None:
2025-07-02 04:52:32.196 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.196 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.196 return
2025-07-02 04:52:32.196 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.196 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.196 else:
2025-07-02 04:52:32.196 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.197 eqi = None
2025-07-02 04:52:32.197
2025-07-02 04:52:32.197 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.197 # identical
2025-07-02 04:52:32.197
2025-07-02 04:52:32.197 # pump out diffs from before the synch point
2025-07-02 04:52:32.197 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.197
2025-07-02 04:52:32.197 # do intraline marking on the synch pair
2025-07-02 04:52:32.197 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.197 if eqi is None:
2025-07-02 04:52:32.197 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.197 atags = btags = ""
2025-07-02 04:52:32.197 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.197 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.197 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.197 if tag == 'replace':
2025-07-02 04:52:32.197 atags += '^' * la
2025-07-02 04:52:32.197 btags += '^' * lb
2025-07-02 04:52:32.197 elif tag == 'delete':
2025-07-02 04:52:32.197 atags += '-' * la
2025-07-02 04:52:32.198 elif tag == 'insert':
2025-07-02 04:52:32.198 btags += '+' * lb
2025-07-02 04:52:32.198 elif tag == 'equal':
2025-07-02 04:52:32.198 atags += ' ' * la
2025-07-02 04:52:32.198 btags += ' ' * lb
2025-07-02 04:52:32.198 else:
2025-07-02 04:52:32.198 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.198 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.198 else:
2025-07-02 04:52:32.198 # the synch pair is identical
2025-07-02 04:52:32.198 yield ' ' + aelt
2025-07-02 04:52:32.198
2025-07-02 04:52:32.198 # pump out diffs from after the synch point
2025-07-02 04:52:32.198 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.198
2025-07-02 04:52:32.198 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.198 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.198
2025-07-02 04:52:32.198 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.198 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.199 alo = 183, ahi = 1101
2025-07-02 04:52:32.199 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.199 blo = 183, bhi = 1101
2025-07-02 04:52:32.199
2025-07-02 04:52:32.199 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.199 g = []
2025-07-02 04:52:32.199 if alo < ahi:
2025-07-02 04:52:32.199 if blo < bhi:
2025-07-02 04:52:32.199 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.199 else:
2025-07-02 04:52:32.199 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.199 elif blo < bhi:
2025-07-02 04:52:32.199 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.199
2025-07-02 04:52:32.199 > yield from g
2025-07-02 04:52:32.199
2025-07-02 04:52:32.199 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.199 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.199
2025-07-02 04:52:32.199 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.199 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.200 alo = 183, ahi = 1101
2025-07-02 04:52:32.200 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.200 blo = 183, bhi = 1101
2025-07-02 04:52:32.200
2025-07-02 04:52:32.200 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.200 r"""
2025-07-02 04:52:32.200 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.200 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.200 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.200 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.200
2025-07-02 04:52:32.200 Example:
2025-07-02 04:52:32.200
2025-07-02 04:52:32.200 >>> d = Differ()
2025-07-02 04:52:32.200 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.200 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.200 >>> print(''.join(results), end="")
2025-07-02 04:52:32.200 - abcDefghiJkl
2025-07-02 04:52:32.200 + abcdefGhijkl
2025-07-02 04:52:32.200 """
2025-07-02 04:52:32.201
2025-07-02 04:52:32.201 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.201 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.201 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.201 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.201 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.201
2025-07-02 04:52:32.201 # search for the pair that matches best without being identical
2025-07-02 04:52:32.201 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.201 # on junk -- unless we have to)
2025-07-02 04:52:32.201 for j in range(blo, bhi):
2025-07-02 04:52:32.201 bj = b[j]
2025-07-02 04:52:32.201 cruncher.set_seq2(bj)
2025-07-02 04:52:32.201 for i in range(alo, ahi):
2025-07-02 04:52:32.201 ai = a[i]
2025-07-02 04:52:32.201 if ai == bj:
2025-07-02 04:52:32.201 if eqi is None:
2025-07-02 04:52:32.201 eqi, eqj = i, j
2025-07-02 04:52:32.201 continue
2025-07-02 04:52:32.201 cruncher.set_seq1(ai)
2025-07-02 04:52:32.202 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.202 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.202 # compares by a factor of 3.
2025-07-02 04:52:32.202 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.202 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.202 # of the computation is cached by cruncher
2025-07-02 04:52:32.202 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.202 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.202 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.202 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.202 if best_ratio < cutoff:
2025-07-02 04:52:32.202 # no non-identical "pretty close" pair
2025-07-02 04:52:32.202 if eqi is None:
2025-07-02 04:52:32.202 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.202 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.202 return
2025-07-02 04:52:32.202 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.202 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.202 else:
2025-07-02 04:52:32.202 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.203 eqi = None
2025-07-02 04:52:32.203
2025-07-02 04:52:32.203 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.203 # identical
2025-07-02 04:52:32.203
2025-07-02 04:52:32.203 # pump out diffs from before the synch point
2025-07-02 04:52:32.203 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.203
2025-07-02 04:52:32.203 # do intraline marking on the synch pair
2025-07-02 04:52:32.203 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.203 if eqi is None:
2025-07-02 04:52:32.203 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.203 atags = btags = ""
2025-07-02 04:52:32.203 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.203 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.203 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.203 if tag == 'replace':
2025-07-02 04:52:32.203 atags += '^' * la
2025-07-02 04:52:32.203 btags += '^' * lb
2025-07-02 04:52:32.203 elif tag == 'delete':
2025-07-02 04:52:32.203 atags += '-' * la
2025-07-02 04:52:32.204 elif tag == 'insert':
2025-07-02 04:52:32.204 btags += '+' * lb
2025-07-02 04:52:32.204 elif tag == 'equal':
2025-07-02 04:52:32.204 atags += ' ' * la
2025-07-02 04:52:32.204 btags += ' ' * lb
2025-07-02 04:52:32.204 else:
2025-07-02 04:52:32.204 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.204 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.204 else:
2025-07-02 04:52:32.204 # the synch pair is identical
2025-07-02 04:52:32.204 yield ' ' + aelt
2025-07-02 04:52:32.204
2025-07-02 04:52:32.204 # pump out diffs from after the synch point
2025-07-02 04:52:32.204 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.204
2025-07-02 04:52:32.204 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.204 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.204
2025-07-02 04:52:32.204 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.204 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.204 alo = 184, ahi = 1101
2025-07-02 04:52:32.204 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.205 blo = 184, bhi = 1101
2025-07-02 04:52:32.205
2025-07-02 04:52:32.205 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.205 g = []
2025-07-02 04:52:32.205 if alo < ahi:
2025-07-02 04:52:32.205 if blo < bhi:
2025-07-02 04:52:32.205 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.205 else:
2025-07-02 04:52:32.205 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.205 elif blo < bhi:
2025-07-02 04:52:32.205 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.205
2025-07-02 04:52:32.205 > yield from g
2025-07-02 04:52:32.205
2025-07-02 04:52:32.205 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.205 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.205
2025-07-02 04:52:32.205 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.205 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.205 alo = 184, ahi = 1101
2025-07-02 04:52:32.205 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.206 blo = 184, bhi = 1101
2025-07-02 04:52:32.206
2025-07-02 04:52:32.206 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.206 r"""
2025-07-02 04:52:32.206 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.206 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.206 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.206 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.206
2025-07-02 04:52:32.206 Example:
2025-07-02 04:52:32.206
2025-07-02 04:52:32.206 >>> d = Differ()
2025-07-02 04:52:32.206 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.206 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.206 >>> print(''.join(results), end="")
2025-07-02 04:52:32.206 - abcDefghiJkl
2025-07-02 04:52:32.206 + abcdefGhijkl
2025-07-02 04:52:32.206 """
2025-07-02 04:52:32.207
2025-07-02 04:52:32.207 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.207 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.207 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.207 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.207 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.207
2025-07-02 04:52:32.207 # search for the pair that matches best without being identical
2025-07-02 04:52:32.207 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.207 # on junk -- unless we have to)
2025-07-02 04:52:32.207 for j in range(blo, bhi):
2025-07-02 04:52:32.207 bj = b[j]
2025-07-02 04:52:32.207 cruncher.set_seq2(bj)
2025-07-02 04:52:32.207 for i in range(alo, ahi):
2025-07-02 04:52:32.207 ai = a[i]
2025-07-02 04:52:32.207 if ai == bj:
2025-07-02 04:52:32.207 if eqi is None:
2025-07-02 04:52:32.207 eqi, eqj = i, j
2025-07-02 04:52:32.207 continue
2025-07-02 04:52:32.207 cruncher.set_seq1(ai)
2025-07-02 04:52:32.207 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.208 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.208 # compares by a factor of 3.
2025-07-02 04:52:32.208 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.208 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.208 # of the computation is cached by cruncher
2025-07-02 04:52:32.208 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.208 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.208 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.208 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.208 if best_ratio < cutoff:
2025-07-02 04:52:32.208 # no non-identical "pretty close" pair
2025-07-02 04:52:32.208 if eqi is None:
2025-07-02 04:52:32.208 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.208 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.208 return
2025-07-02 04:52:32.208 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.208 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.208 else:
2025-07-02 04:52:32.208 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.208 eqi = None
2025-07-02 04:52:32.208
2025-07-02 04:52:32.209 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.209 # identical
2025-07-02 04:52:32.209
2025-07-02 04:52:32.209 # pump out diffs from before the synch point
2025-07-02 04:52:32.209 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.209
2025-07-02 04:52:32.209 # do intraline marking on the synch pair
2025-07-02 04:52:32.209 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.209 if eqi is None:
2025-07-02 04:52:32.209 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.209 atags = btags = ""
2025-07-02 04:52:32.209 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.209 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.209 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.209 if tag == 'replace':
2025-07-02 04:52:32.209 atags += '^' * la
2025-07-02 04:52:32.209 btags += '^' * lb
2025-07-02 04:52:32.209 elif tag == 'delete':
2025-07-02 04:52:32.209 atags += '-' * la
2025-07-02 04:52:32.209 elif tag == 'insert':
2025-07-02 04:52:32.210 btags += '+' * lb
2025-07-02 04:52:32.210 elif tag == 'equal':
2025-07-02 04:52:32.210 atags += ' ' * la
2025-07-02 04:52:32.210 btags += ' ' * lb
2025-07-02 04:52:32.210 else:
2025-07-02 04:52:32.210 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.210 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.210 else:
2025-07-02 04:52:32.210 # the synch pair is identical
2025-07-02 04:52:32.210 yield ' ' + aelt
2025-07-02 04:52:32.210
2025-07-02 04:52:32.210 # pump out diffs from after the synch point
2025-07-02 04:52:32.210 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.210
2025-07-02 04:52:32.210 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.210 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.210
2025-07-02 04:52:32.210 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.210 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.210 alo = 185, ahi = 1101
2025-07-02 04:52:32.210 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.211 blo = 185, bhi = 1101
2025-07-02 04:52:32.211
2025-07-02 04:52:32.211 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.211 g = []
2025-07-02 04:52:32.211 if alo < ahi:
2025-07-02 04:52:32.211 if blo < bhi:
2025-07-02 04:52:32.211 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.211 else:
2025-07-02 04:52:32.211 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.211 elif blo < bhi:
2025-07-02 04:52:32.211 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.211
2025-07-02 04:52:32.211 > yield from g
2025-07-02 04:52:32.211
2025-07-02 04:52:32.211 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.211 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.211
2025-07-02 04:52:32.211 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.211 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.211 alo = 185, ahi = 1101
2025-07-02 04:52:32.211 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.212 blo = 185, bhi = 1101
2025-07-02 04:52:32.212
2025-07-02 04:52:32.212 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.212 r"""
2025-07-02 04:52:32.212 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.212 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.212 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.212 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.212
2025-07-02 04:52:32.212 Example:
2025-07-02 04:52:32.212
2025-07-02 04:52:32.212 >>> d = Differ()
2025-07-02 04:52:32.212 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.212 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.212 >>> print(''.join(results), end="")
2025-07-02 04:52:32.212 - abcDefghiJkl
2025-07-02 04:52:32.212 + abcdefGhijkl
2025-07-02 04:52:32.212 """
2025-07-02 04:52:32.212
2025-07-02 04:52:32.213 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.213 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.213 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.213 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.213 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.213
2025-07-02 04:52:32.213 # search for the pair that matches best without being identical
2025-07-02 04:52:32.213 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.213 # on junk -- unless we have to)
2025-07-02 04:52:32.213 for j in range(blo, bhi):
2025-07-02 04:52:32.213 bj = b[j]
2025-07-02 04:52:32.213 cruncher.set_seq2(bj)
2025-07-02 04:52:32.213 for i in range(alo, ahi):
2025-07-02 04:52:32.213 ai = a[i]
2025-07-02 04:52:32.213 if ai == bj:
2025-07-02 04:52:32.213 if eqi is None:
2025-07-02 04:52:32.213 eqi, eqj = i, j
2025-07-02 04:52:32.213 continue
2025-07-02 04:52:32.213 cruncher.set_seq1(ai)
2025-07-02 04:52:32.213 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.213 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.214 # compares by a factor of 3.
2025-07-02 04:52:32.214 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.214 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.214 # of the computation is cached by cruncher
2025-07-02 04:52:32.214 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.214 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.214 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.214 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.214 if best_ratio < cutoff:
2025-07-02 04:52:32.214 # no non-identical "pretty close" pair
2025-07-02 04:52:32.214 if eqi is None:
2025-07-02 04:52:32.214 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.214 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.214 return
2025-07-02 04:52:32.214 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.214 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.214 else:
2025-07-02 04:52:32.214 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.215 eqi = None
2025-07-02 04:52:32.215
2025-07-02 04:52:32.215 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.215 # identical
2025-07-02 04:52:32.215
2025-07-02 04:52:32.215 # pump out diffs from before the synch point
2025-07-02 04:52:32.215 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.215
2025-07-02 04:52:32.215 # do intraline marking on the synch pair
2025-07-02 04:52:32.215 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.215 if eqi is None:
2025-07-02 04:52:32.215 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.215 atags = btags = ""
2025-07-02 04:52:32.215 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.215 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.215 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.215 if tag == 'replace':
2025-07-02 04:52:32.215 atags += '^' * la
2025-07-02 04:52:32.215 btags += '^' * lb
2025-07-02 04:52:32.215 elif tag == 'delete':
2025-07-02 04:52:32.215 atags += '-' * la
2025-07-02 04:52:32.216 elif tag == 'insert':
2025-07-02 04:52:32.216 btags += '+' * lb
2025-07-02 04:52:32.216 elif tag == 'equal':
2025-07-02 04:52:32.216 atags += ' ' * la
2025-07-02 04:52:32.216 btags += ' ' * lb
2025-07-02 04:52:32.216 else:
2025-07-02 04:52:32.216 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.216 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.216 else:
2025-07-02 04:52:32.216 # the synch pair is identical
2025-07-02 04:52:32.216 yield ' ' + aelt
2025-07-02 04:52:32.216
2025-07-02 04:52:32.216 # pump out diffs from after the synch point
2025-07-02 04:52:32.216 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.216
2025-07-02 04:52:32.216 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.216 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.216
2025-07-02 04:52:32.216 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.216 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.216 alo = 186, ahi = 1101
2025-07-02 04:52:32.216 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.217 blo = 186, bhi = 1101
2025-07-02 04:52:32.217
2025-07-02 04:52:32.217 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.217 g = []
2025-07-02 04:52:32.217 if alo < ahi:
2025-07-02 04:52:32.217 if blo < bhi:
2025-07-02 04:52:32.217 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.217 else:
2025-07-02 04:52:32.217 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.217 elif blo < bhi:
2025-07-02 04:52:32.217 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.217
2025-07-02 04:52:32.217 > yield from g
2025-07-02 04:52:32.217
2025-07-02 04:52:32.217 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.217 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.217
2025-07-02 04:52:32.217 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.217 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.218 alo = 186, ahi = 1101
2025-07-02 04:52:32.218 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.218 blo = 186, bhi = 1101
2025-07-02 04:52:32.218
2025-07-02 04:52:32.218 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.218 r"""
2025-07-02 04:52:32.218 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.218 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.218 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.218 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.218
2025-07-02 04:52:32.218 Example:
2025-07-02 04:52:32.218
2025-07-02 04:52:32.218 >>> d = Differ()
2025-07-02 04:52:32.218 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.218 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.218 >>> print(''.join(results), end="")
2025-07-02 04:52:32.218 - abcDefghiJkl
2025-07-02 04:52:32.218 + abcdefGhijkl
2025-07-02 04:52:32.219 """
2025-07-02 04:52:32.219
2025-07-02 04:52:32.219 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.219 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.219 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.219 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.219 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.219
2025-07-02 04:52:32.219 # search for the pair that matches best without being identical
2025-07-02 04:52:32.219 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.219 # on junk -- unless we have to)
2025-07-02 04:52:32.219 for j in range(blo, bhi):
2025-07-02 04:52:32.219 bj = b[j]
2025-07-02 04:52:32.219 cruncher.set_seq2(bj)
2025-07-02 04:52:32.219 for i in range(alo, ahi):
2025-07-02 04:52:32.219 ai = a[i]
2025-07-02 04:52:32.219 if ai == bj:
2025-07-02 04:52:32.219 if eqi is None:
2025-07-02 04:52:32.219 eqi, eqj = i, j
2025-07-02 04:52:32.219 continue
2025-07-02 04:52:32.220 cruncher.set_seq1(ai)
2025-07-02 04:52:32.220 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.220 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.220 # compares by a factor of 3.
2025-07-02 04:52:32.220 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.220 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.220 # of the computation is cached by cruncher
2025-07-02 04:52:32.220 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.220 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.220 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.220 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.220 if best_ratio < cutoff:
2025-07-02 04:52:32.220 # no non-identical "pretty close" pair
2025-07-02 04:52:32.220 if eqi is None:
2025-07-02 04:52:32.220 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.220 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.220 return
2025-07-02 04:52:32.220 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.220 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.220 else:
2025-07-02 04:52:32.220 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.221 eqi = None
2025-07-02 04:52:32.221
2025-07-02 04:52:32.221 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.221 # identical
2025-07-02 04:52:32.221
2025-07-02 04:52:32.221 # pump out diffs from before the synch point
2025-07-02 04:52:32.221 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.221
2025-07-02 04:52:32.221 # do intraline marking on the synch pair
2025-07-02 04:52:32.221 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.221 if eqi is None:
2025-07-02 04:52:32.221 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.221 atags = btags = ""
2025-07-02 04:52:32.221 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.221 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.221 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.221 if tag == 'replace':
2025-07-02 04:52:32.221 atags += '^' * la
2025-07-02 04:52:32.221 btags += '^' * lb
2025-07-02 04:52:32.221 elif tag == 'delete':
2025-07-02 04:52:32.221 atags += '-' * la
2025-07-02 04:52:32.221 elif tag == 'insert':
2025-07-02 04:52:32.222 btags += '+' * lb
2025-07-02 04:52:32.222 elif tag == 'equal':
2025-07-02 04:52:32.222 atags += ' ' * la
2025-07-02 04:52:32.222 btags += ' ' * lb
2025-07-02 04:52:32.222 else:
2025-07-02 04:52:32.222 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.222 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.222 else:
2025-07-02 04:52:32.222 # the synch pair is identical
2025-07-02 04:52:32.222 yield ' ' + aelt
2025-07-02 04:52:32.222
2025-07-02 04:52:32.222 # pump out diffs from after the synch point
2025-07-02 04:52:32.222 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.222
2025-07-02 04:52:32.222 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.222 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.222
2025-07-02 04:52:32.222 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.222 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.222 alo = 187, ahi = 1101
2025-07-02 04:52:32.222 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.223 blo = 187, bhi = 1101
2025-07-02 04:52:32.223
2025-07-02 04:52:32.223 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.223 g = []
2025-07-02 04:52:32.223 if alo < ahi:
2025-07-02 04:52:32.223 if blo < bhi:
2025-07-02 04:52:32.223 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.223 else:
2025-07-02 04:52:32.223 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.223 elif blo < bhi:
2025-07-02 04:52:32.223 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.223
2025-07-02 04:52:32.223 > yield from g
2025-07-02 04:52:32.223
2025-07-02 04:52:32.223 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.223 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.223
2025-07-02 04:52:32.223 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.223 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.223 alo = 187, ahi = 1101
2025-07-02 04:52:32.223 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.224 blo = 187, bhi = 1101
2025-07-02 04:52:32.224
2025-07-02 04:52:32.224 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.224 r"""
2025-07-02 04:52:32.224 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.224 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.224 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.224 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.224
2025-07-02 04:52:32.224 Example:
2025-07-02 04:52:32.224
2025-07-02 04:52:32.224 >>> d = Differ()
2025-07-02 04:52:32.224 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.224 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.224 >>> print(''.join(results), end="")
2025-07-02 04:52:32.224 - abcDefghiJkl
2025-07-02 04:52:32.224 + abcdefGhijkl
2025-07-02 04:52:32.224 """
2025-07-02 04:52:32.224
2025-07-02 04:52:32.224 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.225 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.225 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.225 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.225 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.225
2025-07-02 04:52:32.225 # search for the pair that matches best without being identical
2025-07-02 04:52:32.225 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.225 # on junk -- unless we have to)
2025-07-02 04:52:32.225 for j in range(blo, bhi):
2025-07-02 04:52:32.225 bj = b[j]
2025-07-02 04:52:32.225 cruncher.set_seq2(bj)
2025-07-02 04:52:32.225 for i in range(alo, ahi):
2025-07-02 04:52:32.225 ai = a[i]
2025-07-02 04:52:32.225 if ai == bj:
2025-07-02 04:52:32.225 if eqi is None:
2025-07-02 04:52:32.225 eqi, eqj = i, j
2025-07-02 04:52:32.225 continue
2025-07-02 04:52:32.225 cruncher.set_seq1(ai)
2025-07-02 04:52:32.225 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.225 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.225 # compares by a factor of 3.
2025-07-02 04:52:32.226 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.226 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.226 # of the computation is cached by cruncher
2025-07-02 04:52:32.226 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.226 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.226 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.226 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.226 if best_ratio < cutoff:
2025-07-02 04:52:32.226 # no non-identical "pretty close" pair
2025-07-02 04:52:32.226 if eqi is None:
2025-07-02 04:52:32.226 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.226 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.226 return
2025-07-02 04:52:32.226 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.226 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.226 else:
2025-07-02 04:52:32.226 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.226 eqi = None
2025-07-02 04:52:32.226
2025-07-02 04:52:32.226 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.227 # identical
2025-07-02 04:52:32.227
2025-07-02 04:52:32.227 # pump out diffs from before the synch point
2025-07-02 04:52:32.227 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.227
2025-07-02 04:52:32.227 # do intraline marking on the synch pair
2025-07-02 04:52:32.227 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.227 if eqi is None:
2025-07-02 04:52:32.227 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.227 atags = btags = ""
2025-07-02 04:52:32.227 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.227 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.227 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.227 if tag == 'replace':
2025-07-02 04:52:32.227 atags += '^' * la
2025-07-02 04:52:32.227 btags += '^' * lb
2025-07-02 04:52:32.227 elif tag == 'delete':
2025-07-02 04:52:32.227 atags += '-' * la
2025-07-02 04:52:32.227 elif tag == 'insert':
2025-07-02 04:52:32.227 btags += '+' * lb
2025-07-02 04:52:32.228 elif tag == 'equal':
2025-07-02 04:52:32.228 atags += ' ' * la
2025-07-02 04:52:32.228 btags += ' ' * lb
2025-07-02 04:52:32.228 else:
2025-07-02 04:52:32.228 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.228 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.228 else:
2025-07-02 04:52:32.228 # the synch pair is identical
2025-07-02 04:52:32.228 yield ' ' + aelt
2025-07-02 04:52:32.228
2025-07-02 04:52:32.228 # pump out diffs from after the synch point
2025-07-02 04:52:32.228 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.228
2025-07-02 04:52:32.228 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.228 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.228
2025-07-02 04:52:32.228 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.228 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.228 alo = 188, ahi = 1101
2025-07-02 04:52:32.228 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.228 blo = 188, bhi = 1101
2025-07-02 04:52:32.229
2025-07-02 04:52:32.229 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.229 g = []
2025-07-02 04:52:32.229 if alo < ahi:
2025-07-02 04:52:32.229 if blo < bhi:
2025-07-02 04:52:32.229 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.229 else:
2025-07-02 04:52:32.229 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.229 elif blo < bhi:
2025-07-02 04:52:32.229 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.229
2025-07-02 04:52:32.229 > yield from g
2025-07-02 04:52:32.229
2025-07-02 04:52:32.229 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.229 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.229
2025-07-02 04:52:32.229 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.229 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.229 alo = 188, ahi = 1101
2025-07-02 04:52:32.229 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.229 blo = 188, bhi = 1101
2025-07-02 04:52:32.230
2025-07-02 04:52:32.230 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.230 r"""
2025-07-02 04:52:32.230 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.230 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.230 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.230 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.230
2025-07-02 04:52:32.230 Example:
2025-07-02 04:52:32.230
2025-07-02 04:52:32.230 >>> d = Differ()
2025-07-02 04:52:32.230 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.230 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.230 >>> print(''.join(results), end="")
2025-07-02 04:52:32.230 - abcDefghiJkl
2025-07-02 04:52:32.230 + abcdefGhijkl
2025-07-02 04:52:32.230 """
2025-07-02 04:52:32.230
2025-07-02 04:52:32.231 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.231 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.231 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.231 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.231 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.231
2025-07-02 04:52:32.231 # search for the pair that matches best without being identical
2025-07-02 04:52:32.231 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.231 # on junk -- unless we have to)
2025-07-02 04:52:32.231 for j in range(blo, bhi):
2025-07-02 04:52:32.231 bj = b[j]
2025-07-02 04:52:32.231 cruncher.set_seq2(bj)
2025-07-02 04:52:32.231 for i in range(alo, ahi):
2025-07-02 04:52:32.231 ai = a[i]
2025-07-02 04:52:32.231 if ai == bj:
2025-07-02 04:52:32.231 if eqi is None:
2025-07-02 04:52:32.231 eqi, eqj = i, j
2025-07-02 04:52:32.231 continue
2025-07-02 04:52:32.231 cruncher.set_seq1(ai)
2025-07-02 04:52:32.231 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.231 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.232 # compares by a factor of 3.
2025-07-02 04:52:32.232 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.232 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.232 # of the computation is cached by cruncher
2025-07-02 04:52:32.232 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.232 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.232 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.232 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.232 if best_ratio < cutoff:
2025-07-02 04:52:32.232 # no non-identical "pretty close" pair
2025-07-02 04:52:32.232 if eqi is None:
2025-07-02 04:52:32.232 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.232 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.232 return
2025-07-02 04:52:32.232 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.232 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.232 else:
2025-07-02 04:52:32.232 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.232 eqi = None
2025-07-02 04:52:32.232
2025-07-02 04:52:32.232 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.232 # identical
2025-07-02 04:52:32.233
2025-07-02 04:52:32.233 # pump out diffs from before the synch point
2025-07-02 04:52:32.233 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.233
2025-07-02 04:52:32.233 # do intraline marking on the synch pair
2025-07-02 04:52:32.233 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.233 if eqi is None:
2025-07-02 04:52:32.233 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.233 atags = btags = ""
2025-07-02 04:52:32.233 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.233 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.233 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.233 if tag == 'replace':
2025-07-02 04:52:32.233 atags += '^' * la
2025-07-02 04:52:32.233 btags += '^' * lb
2025-07-02 04:52:32.233 elif tag == 'delete':
2025-07-02 04:52:32.233 atags += '-' * la
2025-07-02 04:52:32.233 elif tag == 'insert':
2025-07-02 04:52:32.233 btags += '+' * lb
2025-07-02 04:52:32.233 elif tag == 'equal':
2025-07-02 04:52:32.233 atags += ' ' * la
2025-07-02 04:52:32.234 btags += ' ' * lb
2025-07-02 04:52:32.234 else:
2025-07-02 04:52:32.234 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.234 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.234 else:
2025-07-02 04:52:32.234 # the synch pair is identical
2025-07-02 04:52:32.234 yield ' ' + aelt
2025-07-02 04:52:32.234
2025-07-02 04:52:32.234 # pump out diffs from after the synch point
2025-07-02 04:52:32.234 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.234
2025-07-02 04:52:32.234 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.234 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.234
2025-07-02 04:52:32.234 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.234 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.234 alo = 189, ahi = 1101
2025-07-02 04:52:32.234 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.234 blo = 189, bhi = 1101
2025-07-02 04:52:32.234
2025-07-02 04:52:32.235 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.235 g = []
2025-07-02 04:52:32.235 if alo < ahi:
2025-07-02 04:52:32.235 if blo < bhi:
2025-07-02 04:52:32.235 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.235 else:
2025-07-02 04:52:32.235 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.235 elif blo < bhi:
2025-07-02 04:52:32.235 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.235
2025-07-02 04:52:32.235 > yield from g
2025-07-02 04:52:32.235
2025-07-02 04:52:32.235 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.235 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.235
2025-07-02 04:52:32.235 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.235 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.235 alo = 189, ahi = 1101
2025-07-02 04:52:32.235 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.235 blo = 189, bhi = 1101
2025-07-02 04:52:32.235
2025-07-02 04:52:32.236 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.236 r"""
2025-07-02 04:52:32.236 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.236 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.236 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.236 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.236
2025-07-02 04:52:32.236 Example:
2025-07-02 04:52:32.236
2025-07-02 04:52:32.236 >>> d = Differ()
2025-07-02 04:52:32.236 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.236 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.236 >>> print(''.join(results), end="")
2025-07-02 04:52:32.236 - abcDefghiJkl
2025-07-02 04:52:32.236 + abcdefGhijkl
2025-07-02 04:52:32.236 """
2025-07-02 04:52:32.236
2025-07-02 04:52:32.236 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.236 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.237 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.237 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.237 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.237
2025-07-02 04:52:32.237 # search for the pair that matches best without being identical
2025-07-02 04:52:32.237 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.237 # on junk -- unless we have to)
2025-07-02 04:52:32.237 for j in range(blo, bhi):
2025-07-02 04:52:32.237 bj = b[j]
2025-07-02 04:52:32.237 cruncher.set_seq2(bj)
2025-07-02 04:52:32.237 for i in range(alo, ahi):
2025-07-02 04:52:32.237 ai = a[i]
2025-07-02 04:52:32.237 if ai == bj:
2025-07-02 04:52:32.237 if eqi is None:
2025-07-02 04:52:32.237 eqi, eqj = i, j
2025-07-02 04:52:32.237 continue
2025-07-02 04:52:32.237 cruncher.set_seq1(ai)
2025-07-02 04:52:32.237 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.237 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.237 # compares by a factor of 3.
2025-07-02 04:52:32.237 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.238 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.238 # of the computation is cached by cruncher
2025-07-02 04:52:32.238 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.238 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.238 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.238 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.238 if best_ratio < cutoff:
2025-07-02 04:52:32.238 # no non-identical "pretty close" pair
2025-07-02 04:52:32.238 if eqi is None:
2025-07-02 04:52:32.238 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.238 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.238 return
2025-07-02 04:52:32.238 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.238 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.238 else:
2025-07-02 04:52:32.238 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.238 eqi = None
2025-07-02 04:52:32.238
2025-07-02 04:52:32.238 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.238 # identical
2025-07-02 04:52:32.238
2025-07-02 04:52:32.238 # pump out diffs from before the synch point
2025-07-02 04:52:32.239 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.239
2025-07-02 04:52:32.239 # do intraline marking on the synch pair
2025-07-02 04:52:32.239 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.239 if eqi is None:
2025-07-02 04:52:32.239 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.239 atags = btags = ""
2025-07-02 04:52:32.239 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.239 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.239 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.239 if tag == 'replace':
2025-07-02 04:52:32.239 atags += '^' * la
2025-07-02 04:52:32.239 btags += '^' * lb
2025-07-02 04:52:32.239 elif tag == 'delete':
2025-07-02 04:52:32.239 atags += '-' * la
2025-07-02 04:52:32.239 elif tag == 'insert':
2025-07-02 04:52:32.239 btags += '+' * lb
2025-07-02 04:52:32.239 elif tag == 'equal':
2025-07-02 04:52:32.239 atags += ' ' * la
2025-07-02 04:52:32.239 btags += ' ' * lb
2025-07-02 04:52:32.239 else:
2025-07-02 04:52:32.240 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.240 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.240 else:
2025-07-02 04:52:32.240 # the synch pair is identical
2025-07-02 04:52:32.240 yield ' ' + aelt
2025-07-02 04:52:32.240
2025-07-02 04:52:32.240 # pump out diffs from after the synch point
2025-07-02 04:52:32.240 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.240
2025-07-02 04:52:32.240 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.240 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.240
2025-07-02 04:52:32.240 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.240 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.240 alo = 190, ahi = 1101
2025-07-02 04:52:32.240 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.240 blo = 190, bhi = 1101
2025-07-02 04:52:32.240
2025-07-02 04:52:32.240 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.240 g = []
2025-07-02 04:52:32.240 if alo < ahi:
2025-07-02 04:52:32.241 if blo < bhi:
2025-07-02 04:52:32.241 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.241 else:
2025-07-02 04:52:32.241 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.241 elif blo < bhi:
2025-07-02 04:52:32.241 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.241
2025-07-02 04:52:32.241 > yield from g
2025-07-02 04:52:32.241
2025-07-02 04:52:32.241 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.241 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.241
2025-07-02 04:52:32.241 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.241 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.241 alo = 190, ahi = 1101
2025-07-02 04:52:32.241 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.241 blo = 190, bhi = 1101
2025-07-02 04:52:32.241
2025-07-02 04:52:32.241 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.241 r"""
2025-07-02 04:52:32.241 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.241 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.242 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.242 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.242
2025-07-02 04:52:32.242 Example:
2025-07-02 04:52:32.242
2025-07-02 04:52:32.242 >>> d = Differ()
2025-07-02 04:52:32.242 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.242 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.242 >>> print(''.join(results), end="")
2025-07-02 04:52:32.242 - abcDefghiJkl
2025-07-02 04:52:32.242 + abcdefGhijkl
2025-07-02 04:52:32.242 """
2025-07-02 04:52:32.242
2025-07-02 04:52:32.242 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.242 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.242 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.242 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.242 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.243
2025-07-02 04:52:32.243 # search for the pair that matches best without being identical
2025-07-02 04:52:32.243 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.243 # on junk -- unless we have to)
2025-07-02 04:52:32.243 for j in range(blo, bhi):
2025-07-02 04:52:32.243 bj = b[j]
2025-07-02 04:52:32.243 cruncher.set_seq2(bj)
2025-07-02 04:52:32.243 for i in range(alo, ahi):
2025-07-02 04:52:32.243 ai = a[i]
2025-07-02 04:52:32.243 if ai == bj:
2025-07-02 04:52:32.243 if eqi is None:
2025-07-02 04:52:32.243 eqi, eqj = i, j
2025-07-02 04:52:32.243 continue
2025-07-02 04:52:32.243 cruncher.set_seq1(ai)
2025-07-02 04:52:32.243 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.243 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.243 # compares by a factor of 3.
2025-07-02 04:52:32.243 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.243 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.243 # of the computation is cached by cruncher
2025-07-02 04:52:32.244 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.244 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.244 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.244 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.244 if best_ratio < cutoff:
2025-07-02 04:52:32.244 # no non-identical "pretty close" pair
2025-07-02 04:52:32.244 if eqi is None:
2025-07-02 04:52:32.244 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.244 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.244 return
2025-07-02 04:52:32.244 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.244 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.244 else:
2025-07-02 04:52:32.244 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.244 eqi = None
2025-07-02 04:52:32.244
2025-07-02 04:52:32.244 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.244 # identical
2025-07-02 04:52:32.244
2025-07-02 04:52:32.244 # pump out diffs from before the synch point
2025-07-02 04:52:32.245 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.245
2025-07-02 04:52:32.245 # do intraline marking on the synch pair
2025-07-02 04:52:32.245 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.245 if eqi is None:
2025-07-02 04:52:32.245 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.245 atags = btags = ""
2025-07-02 04:52:32.245 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.245 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.245 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.245 if tag == 'replace':
2025-07-02 04:52:32.245 atags += '^' * la
2025-07-02 04:52:32.245 btags += '^' * lb
2025-07-02 04:52:32.245 elif tag == 'delete':
2025-07-02 04:52:32.245 atags += '-' * la
2025-07-02 04:52:32.245 elif tag == 'insert':
2025-07-02 04:52:32.245 btags += '+' * lb
2025-07-02 04:52:32.245 elif tag == 'equal':
2025-07-02 04:52:32.245 atags += ' ' * la
2025-07-02 04:52:32.245 btags += ' ' * lb
2025-07-02 04:52:32.245 else:
2025-07-02 04:52:32.245 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.246 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.246 else:
2025-07-02 04:52:32.246 # the synch pair is identical
2025-07-02 04:52:32.246 yield ' ' + aelt
2025-07-02 04:52:32.246
2025-07-02 04:52:32.246 # pump out diffs from after the synch point
2025-07-02 04:52:32.246 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.246
2025-07-02 04:52:32.246 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.246 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.246
2025-07-02 04:52:32.246 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.246 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.246 alo = 191, ahi = 1101
2025-07-02 04:52:32.246 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.246 blo = 191, bhi = 1101
2025-07-02 04:52:32.246
2025-07-02 04:52:32.246 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.247 g = []
2025-07-02 04:52:32.247 if alo < ahi:
2025-07-02 04:52:32.247 if blo < bhi:
2025-07-02 04:52:32.247 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.247 else:
2025-07-02 04:52:32.247 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.247 elif blo < bhi:
2025-07-02 04:52:32.247 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.247
2025-07-02 04:52:32.247 > yield from g
2025-07-02 04:52:32.247
2025-07-02 04:52:32.247 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.247 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.247
2025-07-02 04:52:32.247 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.247 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.247 alo = 191, ahi = 1101
2025-07-02 04:52:32.247 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.247 blo = 191, bhi = 1101
2025-07-02 04:52:32.247
2025-07-02 04:52:32.247 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.248 r"""
2025-07-02 04:52:32.248 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.248 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.248 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.248 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.248
2025-07-02 04:52:32.248 Example:
2025-07-02 04:52:32.248
2025-07-02 04:52:32.248 >>> d = Differ()
2025-07-02 04:52:32.248 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.248 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.248 >>> print(''.join(results), end="")
2025-07-02 04:52:32.248 - abcDefghiJkl
2025-07-02 04:52:32.248 + abcdefGhijkl
2025-07-02 04:52:32.248 """
2025-07-02 04:52:32.248
2025-07-02 04:52:32.248 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.248 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.248 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.248 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.249 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.249
2025-07-02 04:52:32.249 # search for the pair that matches best without being identical
2025-07-02 04:52:32.249 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.249 # on junk -- unless we have to)
2025-07-02 04:52:32.249 for j in range(blo, bhi):
2025-07-02 04:52:32.249 bj = b[j]
2025-07-02 04:52:32.249 cruncher.set_seq2(bj)
2025-07-02 04:52:32.249 for i in range(alo, ahi):
2025-07-02 04:52:32.249 ai = a[i]
2025-07-02 04:52:32.249 if ai == bj:
2025-07-02 04:52:32.249 if eqi is None:
2025-07-02 04:52:32.249 eqi, eqj = i, j
2025-07-02 04:52:32.249 continue
2025-07-02 04:52:32.249 cruncher.set_seq1(ai)
2025-07-02 04:52:32.249 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.249 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.249 # compares by a factor of 3.
2025-07-02 04:52:32.249 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.249 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.249 # of the computation is cached by cruncher
2025-07-02 04:52:32.250 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.250 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.250 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.250 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.250 if best_ratio < cutoff:
2025-07-02 04:52:32.250 # no non-identical "pretty close" pair
2025-07-02 04:52:32.250 if eqi is None:
2025-07-02 04:52:32.250 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.250 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.250 return
2025-07-02 04:52:32.250 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.250 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.250 else:
2025-07-02 04:52:32.250 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.250 eqi = None
2025-07-02 04:52:32.250
2025-07-02 04:52:32.250 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.250 # identical
2025-07-02 04:52:32.250
2025-07-02 04:52:32.250 # pump out diffs from before the synch point
2025-07-02 04:52:32.251 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.251
2025-07-02 04:52:32.251 # do intraline marking on the synch pair
2025-07-02 04:52:32.251 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.251 if eqi is None:
2025-07-02 04:52:32.251 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.251 atags = btags = ""
2025-07-02 04:52:32.251 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.251 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.251 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.251 if tag == 'replace':
2025-07-02 04:52:32.251 atags += '^' * la
2025-07-02 04:52:32.251 btags += '^' * lb
2025-07-02 04:52:32.251 elif tag == 'delete':
2025-07-02 04:52:32.251 atags += '-' * la
2025-07-02 04:52:32.251 elif tag == 'insert':
2025-07-02 04:52:32.251 btags += '+' * lb
2025-07-02 04:52:32.251 elif tag == 'equal':
2025-07-02 04:52:32.251 atags += ' ' * la
2025-07-02 04:52:32.251 btags += ' ' * lb
2025-07-02 04:52:32.252 else:
2025-07-02 04:52:32.252 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.252 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.252 else:
2025-07-02 04:52:32.252 # the synch pair is identical
2025-07-02 04:52:32.252 yield ' ' + aelt
2025-07-02 04:52:32.252
2025-07-02 04:52:32.252 # pump out diffs from after the synch point
2025-07-02 04:52:32.252 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.252
2025-07-02 04:52:32.252 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.252 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.252
2025-07-02 04:52:32.252 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.252 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.252 alo = 192, ahi = 1101
2025-07-02 04:52:32.252 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.252 blo = 192, bhi = 1101
2025-07-02 04:52:32.252
2025-07-02 04:52:32.252 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.252 g = []
2025-07-02 04:52:32.253 if alo < ahi:
2025-07-02 04:52:32.253 if blo < bhi:
2025-07-02 04:52:32.253 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.253 else:
2025-07-02 04:52:32.253 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.253 elif blo < bhi:
2025-07-02 04:52:32.253 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.253
2025-07-02 04:52:32.253 > yield from g
2025-07-02 04:52:32.253
2025-07-02 04:52:32.253 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.253 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.253
2025-07-02 04:52:32.253 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.253 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.253 alo = 192, ahi = 1101
2025-07-02 04:52:32.253 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.253 blo = 192, bhi = 1101
2025-07-02 04:52:32.253
2025-07-02 04:52:32.253 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.253 r"""
2025-07-02 04:52:32.254 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.254 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.254 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.254 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.254
2025-07-02 04:52:32.254 Example:
2025-07-02 04:52:32.254
2025-07-02 04:52:32.254 >>> d = Differ()
2025-07-02 04:52:32.254 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.254 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.254 >>> print(''.join(results), end="")
2025-07-02 04:52:32.254 - abcDefghiJkl
2025-07-02 04:52:32.254 + abcdefGhijkl
2025-07-02 04:52:32.254 """
2025-07-02 04:52:32.254
2025-07-02 04:52:32.254 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.254 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.254 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.254 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.254 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.255
2025-07-02 04:52:32.255 # search for the pair that matches best without being identical
2025-07-02 04:52:32.255 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.255 # on junk -- unless we have to)
2025-07-02 04:52:32.255 for j in range(blo, bhi):
2025-07-02 04:52:32.255 bj = b[j]
2025-07-02 04:52:32.255 cruncher.set_seq2(bj)
2025-07-02 04:52:32.255 for i in range(alo, ahi):
2025-07-02 04:52:32.255 ai = a[i]
2025-07-02 04:52:32.255 if ai == bj:
2025-07-02 04:52:32.255 if eqi is None:
2025-07-02 04:52:32.255 eqi, eqj = i, j
2025-07-02 04:52:32.255 continue
2025-07-02 04:52:32.255 cruncher.set_seq1(ai)
2025-07-02 04:52:32.255 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.255 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.255 # compares by a factor of 3.
2025-07-02 04:52:32.255 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.255 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.255 # of the computation is cached by cruncher
2025-07-02 04:52:32.255 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.256 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.256 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.256 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.256 if best_ratio < cutoff:
2025-07-02 04:52:32.256 # no non-identical "pretty close" pair
2025-07-02 04:52:32.256 if eqi is None:
2025-07-02 04:52:32.256 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.256 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.256 return
2025-07-02 04:52:32.256 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.256 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.256 else:
2025-07-02 04:52:32.256 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.256 eqi = None
2025-07-02 04:52:32.256
2025-07-02 04:52:32.256 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.256 # identical
2025-07-02 04:52:32.256
2025-07-02 04:52:32.256 # pump out diffs from before the synch point
2025-07-02 04:52:32.256 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.256
2025-07-02 04:52:32.256 # do intraline marking on the synch pair
2025-07-02 04:52:32.257 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.257 if eqi is None:
2025-07-02 04:52:32.257 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.257 atags = btags = ""
2025-07-02 04:52:32.257 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.257 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.257 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.257 if tag == 'replace':
2025-07-02 04:52:32.257 atags += '^' * la
2025-07-02 04:52:32.257 btags += '^' * lb
2025-07-02 04:52:32.257 elif tag == 'delete':
2025-07-02 04:52:32.257 atags += '-' * la
2025-07-02 04:52:32.257 elif tag == 'insert':
2025-07-02 04:52:32.257 btags += '+' * lb
2025-07-02 04:52:32.257 elif tag == 'equal':
2025-07-02 04:52:32.257 atags += ' ' * la
2025-07-02 04:52:32.257 btags += ' ' * lb
2025-07-02 04:52:32.257 else:
2025-07-02 04:52:32.257 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.257 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.258 else:
2025-07-02 04:52:32.258 # the synch pair is identical
2025-07-02 04:52:32.258 yield ' ' + aelt
2025-07-02 04:52:32.258
2025-07-02 04:52:32.258 # pump out diffs from after the synch point
2025-07-02 04:52:32.258 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.258
2025-07-02 04:52:32.258 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.258 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.258
2025-07-02 04:52:32.258 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.258 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.258 alo = 193, ahi = 1101
2025-07-02 04:52:32.258 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.258 blo = 193, bhi = 1101
2025-07-02 04:52:32.258
2025-07-02 04:52:32.258 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.258 g = []
2025-07-02 04:52:32.258 if alo < ahi:
2025-07-02 04:52:32.258 if blo < bhi:
2025-07-02 04:52:32.258 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.259 else:
2025-07-02 04:52:32.259 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.259 elif blo < bhi:
2025-07-02 04:52:32.259 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.259
2025-07-02 04:52:32.259 > yield from g
2025-07-02 04:52:32.259
2025-07-02 04:52:32.259 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.259 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.259
2025-07-02 04:52:32.259 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.259 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.259 alo = 193, ahi = 1101
2025-07-02 04:52:32.259 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.259 blo = 193, bhi = 1101
2025-07-02 04:52:32.259
2025-07-02 04:52:32.259 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.259 r"""
2025-07-02 04:52:32.259 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.259 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.260 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.260 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.260
2025-07-02 04:52:32.260 Example:
2025-07-02 04:52:32.260
2025-07-02 04:52:32.260 >>> d = Differ()
2025-07-02 04:52:32.260 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.260 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.260 >>> print(''.join(results), end="")
2025-07-02 04:52:32.260 - abcDefghiJkl
2025-07-02 04:52:32.260 + abcdefGhijkl
2025-07-02 04:52:32.260 """
2025-07-02 04:52:32.260
2025-07-02 04:52:32.260 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.260 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.260 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.260 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.260 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.261
2025-07-02 04:52:32.261 # search for the pair that matches best without being identical
2025-07-02 04:52:32.261 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.261 # on junk -- unless we have to)
2025-07-02 04:52:32.261 for j in range(blo, bhi):
2025-07-02 04:52:32.261 bj = b[j]
2025-07-02 04:52:32.261 cruncher.set_seq2(bj)
2025-07-02 04:52:32.261 for i in range(alo, ahi):
2025-07-02 04:52:32.261 ai = a[i]
2025-07-02 04:52:32.261 if ai == bj:
2025-07-02 04:52:32.261 if eqi is None:
2025-07-02 04:52:32.261 eqi, eqj = i, j
2025-07-02 04:52:32.261 continue
2025-07-02 04:52:32.261 cruncher.set_seq1(ai)
2025-07-02 04:52:32.261 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.261 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.261 # compares by a factor of 3.
2025-07-02 04:52:32.261 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.261 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.261 # of the computation is cached by cruncher
2025-07-02 04:52:32.261 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.261 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.262 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.262 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.262 if best_ratio < cutoff:
2025-07-02 04:52:32.262 # no non-identical "pretty close" pair
2025-07-02 04:52:32.262 if eqi is None:
2025-07-02 04:52:32.262 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.262 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.262 return
2025-07-02 04:52:32.262 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.262 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.262 else:
2025-07-02 04:52:32.262 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.262 eqi = None
2025-07-02 04:52:32.262
2025-07-02 04:52:32.262 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.262 # identical
2025-07-02 04:52:32.262
2025-07-02 04:52:32.262 # pump out diffs from before the synch point
2025-07-02 04:52:32.263 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.263
2025-07-02 04:52:32.263 # do intraline marking on the synch pair
2025-07-02 04:52:32.263 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.263 if eqi is None:
2025-07-02 04:52:32.263 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.263 atags = btags = ""
2025-07-02 04:52:32.263 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.263 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.263 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.263 if tag == 'replace':
2025-07-02 04:52:32.263 atags += '^' * la
2025-07-02 04:52:32.263 btags += '^' * lb
2025-07-02 04:52:32.263 elif tag == 'delete':
2025-07-02 04:52:32.263 atags += '-' * la
2025-07-02 04:52:32.263 elif tag == 'insert':
2025-07-02 04:52:32.263 btags += '+' * lb
2025-07-02 04:52:32.263 elif tag == 'equal':
2025-07-02 04:52:32.263 atags += ' ' * la
2025-07-02 04:52:32.263 btags += ' ' * lb
2025-07-02 04:52:32.263 else:
2025-07-02 04:52:32.263 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.264 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.264 else:
2025-07-02 04:52:32.264 # the synch pair is identical
2025-07-02 04:52:32.264 yield ' ' + aelt
2025-07-02 04:52:32.264
2025-07-02 04:52:32.264 # pump out diffs from after the synch point
2025-07-02 04:52:32.264 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.264
2025-07-02 04:52:32.264 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.264 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.264
2025-07-02 04:52:32.264 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.264 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.264 alo = 194, ahi = 1101
2025-07-02 04:52:32.264 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.264 blo = 194, bhi = 1101
2025-07-02 04:52:32.264
2025-07-02 04:52:32.264 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.264 g = []
2025-07-02 04:52:32.264 if alo < ahi:
2025-07-02 04:52:32.264 if blo < bhi:
2025-07-02 04:52:32.265 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.265 else:
2025-07-02 04:52:32.265 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.265 elif blo < bhi:
2025-07-02 04:52:32.265 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.265
2025-07-02 04:52:32.265 > yield from g
2025-07-02 04:52:32.265
2025-07-02 04:52:32.265 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.265 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.265
2025-07-02 04:52:32.265 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.265 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.265 alo = 194, ahi = 1101
2025-07-02 04:52:32.265 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.265 blo = 194, bhi = 1101
2025-07-02 04:52:32.265
2025-07-02 04:52:32.265 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.265 r"""
2025-07-02 04:52:32.265 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.265 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.266 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.266 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.266
2025-07-02 04:52:32.266 Example:
2025-07-02 04:52:32.266
2025-07-02 04:52:32.266 >>> d = Differ()
2025-07-02 04:52:32.266 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.266 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.266 >>> print(''.join(results), end="")
2025-07-02 04:52:32.266 - abcDefghiJkl
2025-07-02 04:52:32.266 + abcdefGhijkl
2025-07-02 04:52:32.266 """
2025-07-02 04:52:32.266
2025-07-02 04:52:32.266 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.266 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.266 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.266 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.266 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.266
2025-07-02 04:52:32.267 # search for the pair that matches best without being identical
2025-07-02 04:52:32.267 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.267 # on junk -- unless we have to)
2025-07-02 04:52:32.267 for j in range(blo, bhi):
2025-07-02 04:52:32.267 bj = b[j]
2025-07-02 04:52:32.267 cruncher.set_seq2(bj)
2025-07-02 04:52:32.267 for i in range(alo, ahi):
2025-07-02 04:52:32.267 ai = a[i]
2025-07-02 04:52:32.267 if ai == bj:
2025-07-02 04:52:32.267 if eqi is None:
2025-07-02 04:52:32.267 eqi, eqj = i, j
2025-07-02 04:52:32.267 continue
2025-07-02 04:52:32.267 cruncher.set_seq1(ai)
2025-07-02 04:52:32.267 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.267 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.267 # compares by a factor of 3.
2025-07-02 04:52:32.267 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.267 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.267 # of the computation is cached by cruncher
2025-07-02 04:52:32.267 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.268 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.268 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.268 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.268 if best_ratio < cutoff:
2025-07-02 04:52:32.268 # no non-identical "pretty close" pair
2025-07-02 04:52:32.268 if eqi is None:
2025-07-02 04:52:32.268 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.268 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.268 return
2025-07-02 04:52:32.268 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.268 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.268 else:
2025-07-02 04:52:32.268 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.268 eqi = None
2025-07-02 04:52:32.268
2025-07-02 04:52:32.268 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.268 # identical
2025-07-02 04:52:32.268
2025-07-02 04:52:32.268 # pump out diffs from before the synch point
2025-07-02 04:52:32.269 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.269
2025-07-02 04:52:32.269 # do intraline marking on the synch pair
2025-07-02 04:52:32.269 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.269 if eqi is None:
2025-07-02 04:52:32.269 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.269 atags = btags = ""
2025-07-02 04:52:32.269 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.269 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.269 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.269 if tag == 'replace':
2025-07-02 04:52:32.269 atags += '^' * la
2025-07-02 04:52:32.269 btags += '^' * lb
2025-07-02 04:52:32.269 elif tag == 'delete':
2025-07-02 04:52:32.269 atags += '-' * la
2025-07-02 04:52:32.269 elif tag == 'insert':
2025-07-02 04:52:32.269 btags += '+' * lb
2025-07-02 04:52:32.269 elif tag == 'equal':
2025-07-02 04:52:32.269 atags += ' ' * la
2025-07-02 04:52:32.269 btags += ' ' * lb
2025-07-02 04:52:32.269 else:
2025-07-02 04:52:32.269 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.270 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.270 else:
2025-07-02 04:52:32.270 # the synch pair is identical
2025-07-02 04:52:32.270 yield ' ' + aelt
2025-07-02 04:52:32.270
2025-07-02 04:52:32.270 # pump out diffs from after the synch point
2025-07-02 04:52:32.270 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.270
2025-07-02 04:52:32.270 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.270 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.270
2025-07-02 04:52:32.270 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.270 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.270 alo = 195, ahi = 1101
2025-07-02 04:52:32.270 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.270 blo = 195, bhi = 1101
2025-07-02 04:52:32.270
2025-07-02 04:52:32.270 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.270 g = []
2025-07-02 04:52:32.270 if alo < ahi:
2025-07-02 04:52:32.270 if blo < bhi:
2025-07-02 04:52:32.271 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.271 else:
2025-07-02 04:52:32.271 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.271 elif blo < bhi:
2025-07-02 04:52:32.271 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.271
2025-07-02 04:52:32.271 > yield from g
2025-07-02 04:52:32.271
2025-07-02 04:52:32.271 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.271 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.271
2025-07-02 04:52:32.271 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.271 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.271 alo = 195, ahi = 1101
2025-07-02 04:52:32.271 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.271 blo = 195, bhi = 1101
2025-07-02 04:52:32.271
2025-07-02 04:52:32.271 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.271 r"""
2025-07-02 04:52:32.271 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.271 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.272 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.272 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.272
2025-07-02 04:52:32.272 Example:
2025-07-02 04:52:32.272
2025-07-02 04:52:32.272 >>> d = Differ()
2025-07-02 04:52:32.272 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.272 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.272 >>> print(''.join(results), end="")
2025-07-02 04:52:32.272 - abcDefghiJkl
2025-07-02 04:52:32.272 + abcdefGhijkl
2025-07-02 04:52:32.272 """
2025-07-02 04:52:32.272
2025-07-02 04:52:32.272 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.272 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.272 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.272 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.272 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.272
2025-07-02 04:52:32.272 # search for the pair that matches best without being identical
2025-07-02 04:52:32.273 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.273 # on junk -- unless we have to)
2025-07-02 04:52:32.273 for j in range(blo, bhi):
2025-07-02 04:52:32.273 bj = b[j]
2025-07-02 04:52:32.273 cruncher.set_seq2(bj)
2025-07-02 04:52:32.273 for i in range(alo, ahi):
2025-07-02 04:52:32.273 ai = a[i]
2025-07-02 04:52:32.273 if ai == bj:
2025-07-02 04:52:32.273 if eqi is None:
2025-07-02 04:52:32.273 eqi, eqj = i, j
2025-07-02 04:52:32.273 continue
2025-07-02 04:52:32.273 cruncher.set_seq1(ai)
2025-07-02 04:52:32.273 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.273 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.273 # compares by a factor of 3.
2025-07-02 04:52:32.273 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.273 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.273 # of the computation is cached by cruncher
2025-07-02 04:52:32.273 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.273 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.273 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.274 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.274 if best_ratio < cutoff:
2025-07-02 04:52:32.274 # no non-identical "pretty close" pair
2025-07-02 04:52:32.274 if eqi is None:
2025-07-02 04:52:32.274 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.274 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.274 return
2025-07-02 04:52:32.274 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.274 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.274 else:
2025-07-02 04:52:32.274 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.274 eqi = None
2025-07-02 04:52:32.274
2025-07-02 04:52:32.274 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.274 # identical
2025-07-02 04:52:32.274
2025-07-02 04:52:32.274 # pump out diffs from before the synch point
2025-07-02 04:52:32.274 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.274
2025-07-02 04:52:32.274 # do intraline marking on the synch pair
2025-07-02 04:52:32.274 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.275 if eqi is None:
2025-07-02 04:52:32.275 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.275 atags = btags = ""
2025-07-02 04:52:32.275 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.275 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.275 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.275 if tag == 'replace':
2025-07-02 04:52:32.275 atags += '^' * la
2025-07-02 04:52:32.275 btags += '^' * lb
2025-07-02 04:52:32.275 elif tag == 'delete':
2025-07-02 04:52:32.275 atags += '-' * la
2025-07-02 04:52:32.275 elif tag == 'insert':
2025-07-02 04:52:32.275 btags += '+' * lb
2025-07-02 04:52:32.275 elif tag == 'equal':
2025-07-02 04:52:32.275 atags += ' ' * la
2025-07-02 04:52:32.275 btags += ' ' * lb
2025-07-02 04:52:32.275 else:
2025-07-02 04:52:32.275 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.275 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.275 else:
2025-07-02 04:52:32.276 # the synch pair is identical
2025-07-02 04:52:32.276 yield ' ' + aelt
2025-07-02 04:52:32.276
2025-07-02 04:52:32.276 # pump out diffs from after the synch point
2025-07-02 04:52:32.276 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.276
2025-07-02 04:52:32.276 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.276 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.276
2025-07-02 04:52:32.276 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.276 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.276 alo = 196, ahi = 1101
2025-07-02 04:52:32.276 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.276 blo = 196, bhi = 1101
2025-07-02 04:52:32.276
2025-07-02 04:52:32.276 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.276 g = []
2025-07-02 04:52:32.276 if alo < ahi:
2025-07-02 04:52:32.276 if blo < bhi:
2025-07-02 04:52:32.277 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.277 else:
2025-07-02 04:52:32.277 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.277 elif blo < bhi:
2025-07-02 04:52:32.277 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.277
2025-07-02 04:52:32.277 > yield from g
2025-07-02 04:52:32.277
2025-07-02 04:52:32.277 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.277 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.277
2025-07-02 04:52:32.277 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.277 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.277 alo = 196, ahi = 1101
2025-07-02 04:52:32.277 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.277 blo = 196, bhi = 1101
2025-07-02 04:52:32.277
2025-07-02 04:52:32.277 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.277 r"""
2025-07-02 04:52:32.277 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.278 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.278 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.278 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.278
2025-07-02 04:52:32.278 Example:
2025-07-02 04:52:32.278
2025-07-02 04:52:32.278 >>> d = Differ()
2025-07-02 04:52:32.278 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.278 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.278 >>> print(''.join(results), end="")
2025-07-02 04:52:32.278 - abcDefghiJkl
2025-07-02 04:52:32.278 + abcdefGhijkl
2025-07-02 04:52:32.278 """
2025-07-02 04:52:32.278
2025-07-02 04:52:32.278 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.278 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.278 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.278 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.278 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.279
2025-07-02 04:52:32.279 # search for the pair that matches best without being identical
2025-07-02 04:52:32.279 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.279 # on junk -- unless we have to)
2025-07-02 04:52:32.279 for j in range(blo, bhi):
2025-07-02 04:52:32.279 bj = b[j]
2025-07-02 04:52:32.279 cruncher.set_seq2(bj)
2025-07-02 04:52:32.279 for i in range(alo, ahi):
2025-07-02 04:52:32.279 ai = a[i]
2025-07-02 04:52:32.279 if ai == bj:
2025-07-02 04:52:32.279 if eqi is None:
2025-07-02 04:52:32.279 eqi, eqj = i, j
2025-07-02 04:52:32.279 continue
2025-07-02 04:52:32.279 cruncher.set_seq1(ai)
2025-07-02 04:52:32.279 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.279 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.279 # compares by a factor of 3.
2025-07-02 04:52:32.279 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.279 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.279 # of the computation is cached by cruncher
2025-07-02 04:52:32.279 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.279 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.280 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.280 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.280 if best_ratio < cutoff:
2025-07-02 04:52:32.280 # no non-identical "pretty close" pair
2025-07-02 04:52:32.280 if eqi is None:
2025-07-02 04:52:32.280 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.280 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.280 return
2025-07-02 04:52:32.280 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.280 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.280 else:
2025-07-02 04:52:32.280 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.280 eqi = None
2025-07-02 04:52:32.280
2025-07-02 04:52:32.280 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.280 # identical
2025-07-02 04:52:32.280
2025-07-02 04:52:32.280 # pump out diffs from before the synch point
2025-07-02 04:52:32.280 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.280
2025-07-02 04:52:32.280 # do intraline marking on the synch pair
2025-07-02 04:52:32.281 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.281 if eqi is None:
2025-07-02 04:52:32.281 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.281 atags = btags = ""
2025-07-02 04:52:32.281 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.281 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.281 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.281 if tag == 'replace':
2025-07-02 04:52:32.281 atags += '^' * la
2025-07-02 04:52:32.281 btags += '^' * lb
2025-07-02 04:52:32.281 elif tag == 'delete':
2025-07-02 04:52:32.281 atags += '-' * la
2025-07-02 04:52:32.281 elif tag == 'insert':
2025-07-02 04:52:32.281 btags += '+' * lb
2025-07-02 04:52:32.281 elif tag == 'equal':
2025-07-02 04:52:32.281 atags += ' ' * la
2025-07-02 04:52:32.281 btags += ' ' * lb
2025-07-02 04:52:32.281 else:
2025-07-02 04:52:32.281 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.281 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.281 else:
2025-07-02 04:52:32.281 # the synch pair is identical
2025-07-02 04:52:32.282 yield ' ' + aelt
2025-07-02 04:52:32.282
2025-07-02 04:52:32.282 # pump out diffs from after the synch point
2025-07-02 04:52:32.282 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.282
2025-07-02 04:52:32.282 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.282 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.282
2025-07-02 04:52:32.282 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.282 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.282 alo = 197, ahi = 1101
2025-07-02 04:52:32.282 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.282 blo = 197, bhi = 1101
2025-07-02 04:52:32.282
2025-07-02 04:52:32.282 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.282 g = []
2025-07-02 04:52:32.282 if alo < ahi:
2025-07-02 04:52:32.282 if blo < bhi:
2025-07-02 04:52:32.282 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.282 else:
2025-07-02 04:52:32.282 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.283 elif blo < bhi:
2025-07-02 04:52:32.283 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.283
2025-07-02 04:52:32.283 > yield from g
2025-07-02 04:52:32.283
2025-07-02 04:52:32.283 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.283 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.283
2025-07-02 04:52:32.283 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.283 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.283 alo = 197, ahi = 1101
2025-07-02 04:52:32.283 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.283 blo = 197, bhi = 1101
2025-07-02 04:52:32.283
2025-07-02 04:52:32.283 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.283 r"""
2025-07-02 04:52:32.283 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.283 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.283 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.283 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.284
2025-07-02 04:52:32.284 Example:
2025-07-02 04:52:32.284
2025-07-02 04:52:32.284 >>> d = Differ()
2025-07-02 04:52:32.284 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.284 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.284 >>> print(''.join(results), end="")
2025-07-02 04:52:32.284 - abcDefghiJkl
2025-07-02 04:52:32.284 + abcdefGhijkl
2025-07-02 04:52:32.284 """
2025-07-02 04:52:32.284
2025-07-02 04:52:32.284 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.284 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.284 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.284 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.284 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.284
2025-07-02 04:52:32.284 # search for the pair that matches best without being identical
2025-07-02 04:52:32.285 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.285 # on junk -- unless we have to)
2025-07-02 04:52:32.285 for j in range(blo, bhi):
2025-07-02 04:52:32.285 bj = b[j]
2025-07-02 04:52:32.285 cruncher.set_seq2(bj)
2025-07-02 04:52:32.285 for i in range(alo, ahi):
2025-07-02 04:52:32.285 ai = a[i]
2025-07-02 04:52:32.285 if ai == bj:
2025-07-02 04:52:32.285 if eqi is None:
2025-07-02 04:52:32.285 eqi, eqj = i, j
2025-07-02 04:52:32.285 continue
2025-07-02 04:52:32.285 cruncher.set_seq1(ai)
2025-07-02 04:52:32.285 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.285 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.285 # compares by a factor of 3.
2025-07-02 04:52:32.285 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.285 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.285 # of the computation is cached by cruncher
2025-07-02 04:52:32.285 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.285 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.285 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.286 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.286 if best_ratio < cutoff:
2025-07-02 04:52:32.286 # no non-identical "pretty close" pair
2025-07-02 04:52:32.286 if eqi is None:
2025-07-02 04:52:32.286 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.286 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.286 return
2025-07-02 04:52:32.286 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.286 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.286 else:
2025-07-02 04:52:32.286 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.286 eqi = None
2025-07-02 04:52:32.286
2025-07-02 04:52:32.286 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.286 # identical
2025-07-02 04:52:32.286
2025-07-02 04:52:32.286 # pump out diffs from before the synch point
2025-07-02 04:52:32.286 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.286
2025-07-02 04:52:32.286 # do intraline marking on the synch pair
2025-07-02 04:52:32.286 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.286 if eqi is None:
2025-07-02 04:52:32.287 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.287 atags = btags = ""
2025-07-02 04:52:32.287 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.287 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.287 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.287 if tag == 'replace':
2025-07-02 04:52:32.287 atags += '^' * la
2025-07-02 04:52:32.287 btags += '^' * lb
2025-07-02 04:52:32.287 elif tag == 'delete':
2025-07-02 04:52:32.287 atags += '-' * la
2025-07-02 04:52:32.287 elif tag == 'insert':
2025-07-02 04:52:32.287 btags += '+' * lb
2025-07-02 04:52:32.287 elif tag == 'equal':
2025-07-02 04:52:32.287 atags += ' ' * la
2025-07-02 04:52:32.287 btags += ' ' * lb
2025-07-02 04:52:32.287 else:
2025-07-02 04:52:32.287 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.287 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.287 else:
2025-07-02 04:52:32.287 # the synch pair is identical
2025-07-02 04:52:32.287 yield ' ' + aelt
2025-07-02 04:52:32.288
2025-07-02 04:52:32.288 # pump out diffs from after the synch point
2025-07-02 04:52:32.288 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.288
2025-07-02 04:52:32.288 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.288 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.288
2025-07-02 04:52:32.288 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.288 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.288 alo = 198, ahi = 1101
2025-07-02 04:52:32.288 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.288 blo = 198, bhi = 1101
2025-07-02 04:52:32.288
2025-07-02 04:52:32.288 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.288 g = []
2025-07-02 04:52:32.288 if alo < ahi:
2025-07-02 04:52:32.288 if blo < bhi:
2025-07-02 04:52:32.288 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.288 else:
2025-07-02 04:52:32.288 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.288 elif blo < bhi:
2025-07-02 04:52:32.289 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.289
2025-07-02 04:52:32.289 > yield from g
2025-07-02 04:52:32.289
2025-07-02 04:52:32.289 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.289 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.289
2025-07-02 04:52:32.289 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.289 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.289 alo = 198, ahi = 1101
2025-07-02 04:52:32.289 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.289 blo = 198, bhi = 1101
2025-07-02 04:52:32.289
2025-07-02 04:52:32.289 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.289 r"""
2025-07-02 04:52:32.289 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.289 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.289 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.289 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.289
2025-07-02 04:52:32.289 Example:
2025-07-02 04:52:32.290
2025-07-02 04:52:32.290 >>> d = Differ()
2025-07-02 04:52:32.290 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.290 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.290 >>> print(''.join(results), end="")
2025-07-02 04:52:32.290 - abcDefghiJkl
2025-07-02 04:52:32.290 + abcdefGhijkl
2025-07-02 04:52:32.290 """
2025-07-02 04:52:32.290
2025-07-02 04:52:32.290 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.290 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.290 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.290 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.290 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.290
2025-07-02 04:52:32.290 # search for the pair that matches best without being identical
2025-07-02 04:52:32.290 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.290 # on junk -- unless we have to)
2025-07-02 04:52:32.290 for j in range(blo, bhi):
2025-07-02 04:52:32.290 bj = b[j]
2025-07-02 04:52:32.291 cruncher.set_seq2(bj)
2025-07-02 04:52:32.291 for i in range(alo, ahi):
2025-07-02 04:52:32.291 ai = a[i]
2025-07-02 04:52:32.291 if ai == bj:
2025-07-02 04:52:32.291 if eqi is None:
2025-07-02 04:52:32.291 eqi, eqj = i, j
2025-07-02 04:52:32.291 continue
2025-07-02 04:52:32.291 cruncher.set_seq1(ai)
2025-07-02 04:52:32.291 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.291 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.291 # compares by a factor of 3.
2025-07-02 04:52:32.291 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.291 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.291 # of the computation is cached by cruncher
2025-07-02 04:52:32.291 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.291 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.291 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.291 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.291 if best_ratio < cutoff:
2025-07-02 04:52:32.291 # no non-identical "pretty close" pair
2025-07-02 04:52:32.291 if eqi is None:
2025-07-02 04:52:32.292 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.292 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.292 return
2025-07-02 04:52:32.292 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.292 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.292 else:
2025-07-02 04:52:32.292 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.292 eqi = None
2025-07-02 04:52:32.292
2025-07-02 04:52:32.292 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.292 # identical
2025-07-02 04:52:32.292
2025-07-02 04:52:32.292 # pump out diffs from before the synch point
2025-07-02 04:52:32.292 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.292
2025-07-02 04:52:32.292 # do intraline marking on the synch pair
2025-07-02 04:52:32.292 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.292 if eqi is None:
2025-07-02 04:52:32.292 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.292 atags = btags = ""
2025-07-02 04:52:32.292 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.293 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.293 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.293 if tag == 'replace':
2025-07-02 04:52:32.293 atags += '^' * la
2025-07-02 04:52:32.293 btags += '^' * lb
2025-07-02 04:52:32.293 elif tag == 'delete':
2025-07-02 04:52:32.293 atags += '-' * la
2025-07-02 04:52:32.293 elif tag == 'insert':
2025-07-02 04:52:32.293 btags += '+' * lb
2025-07-02 04:52:32.293 elif tag == 'equal':
2025-07-02 04:52:32.293 atags += ' ' * la
2025-07-02 04:52:32.293 btags += ' ' * lb
2025-07-02 04:52:32.293 else:
2025-07-02 04:52:32.293 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.293 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.293 else:
2025-07-02 04:52:32.293 # the synch pair is identical
2025-07-02 04:52:32.293 yield ' ' + aelt
2025-07-02 04:52:32.293
2025-07-02 04:52:32.293 # pump out diffs from after the synch point
2025-07-02 04:52:32.294 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.294
2025-07-02 04:52:32.294 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.294 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.294
2025-07-02 04:52:32.294 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.294 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.294 alo = 199, ahi = 1101
2025-07-02 04:52:32.294 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.294 blo = 199, bhi = 1101
2025-07-02 04:52:32.294
2025-07-02 04:52:32.294 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.294 g = []
2025-07-02 04:52:32.294 if alo < ahi:
2025-07-02 04:52:32.294 if blo < bhi:
2025-07-02 04:52:32.294 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.294 else:
2025-07-02 04:52:32.294 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.294 elif blo < bhi:
2025-07-02 04:52:32.294 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.295
2025-07-02 04:52:32.295 > yield from g
2025-07-02 04:52:32.295
2025-07-02 04:52:32.295 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.295 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.295
2025-07-02 04:52:32.295 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.295 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.295 alo = 199, ahi = 1101
2025-07-02 04:52:32.295 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.295 blo = 199, bhi = 1101
2025-07-02 04:52:32.295
2025-07-02 04:52:32.295 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.295 r"""
2025-07-02 04:52:32.295 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.295 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.295 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.295 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.295
2025-07-02 04:52:32.295 Example:
2025-07-02 04:52:32.295
2025-07-02 04:52:32.296 >>> d = Differ()
2025-07-02 04:52:32.296 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.296 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.296 >>> print(''.join(results), end="")
2025-07-02 04:52:32.296 - abcDefghiJkl
2025-07-02 04:52:32.296 + abcdefGhijkl
2025-07-02 04:52:32.296 """
2025-07-02 04:52:32.296
2025-07-02 04:52:32.296 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.296 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.296 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.296 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.296 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.296
2025-07-02 04:52:32.296 # search for the pair that matches best without being identical
2025-07-02 04:52:32.296 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.296 # on junk -- unless we have to)
2025-07-02 04:52:32.296 for j in range(blo, bhi):
2025-07-02 04:52:32.296 bj = b[j]
2025-07-02 04:52:32.296 cruncher.set_seq2(bj)
2025-07-02 04:52:32.297 for i in range(alo, ahi):
2025-07-02 04:52:32.297 ai = a[i]
2025-07-02 04:52:32.297 if ai == bj:
2025-07-02 04:52:32.297 if eqi is None:
2025-07-02 04:52:32.297 eqi, eqj = i, j
2025-07-02 04:52:32.297 continue
2025-07-02 04:52:32.297 cruncher.set_seq1(ai)
2025-07-02 04:52:32.297 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.297 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.297 # compares by a factor of 3.
2025-07-02 04:52:32.297 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.297 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.297 # of the computation is cached by cruncher
2025-07-02 04:52:32.297 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.297 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.297 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.297 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.297 if best_ratio < cutoff:
2025-07-02 04:52:32.297 # no non-identical "pretty close" pair
2025-07-02 04:52:32.297 if eqi is None:
2025-07-02 04:52:32.297 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.298 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.298 return
2025-07-02 04:52:32.298 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.298 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.298 else:
2025-07-02 04:52:32.298 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.298 eqi = None
2025-07-02 04:52:32.298
2025-07-02 04:52:32.298 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.298 # identical
2025-07-02 04:52:32.298
2025-07-02 04:52:32.298 # pump out diffs from before the synch point
2025-07-02 04:52:32.298 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.298
2025-07-02 04:52:32.298 # do intraline marking on the synch pair
2025-07-02 04:52:32.298 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.298 if eqi is None:
2025-07-02 04:52:32.298 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.298 atags = btags = ""
2025-07-02 04:52:32.298 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.298 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.298 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.299 if tag == 'replace':
2025-07-02 04:52:32.299 atags += '^' * la
2025-07-02 04:52:32.299 btags += '^' * lb
2025-07-02 04:52:32.299 elif tag == 'delete':
2025-07-02 04:52:32.299 atags += '-' * la
2025-07-02 04:52:32.299 elif tag == 'insert':
2025-07-02 04:52:32.299 btags += '+' * lb
2025-07-02 04:52:32.299 elif tag == 'equal':
2025-07-02 04:52:32.299 atags += ' ' * la
2025-07-02 04:52:32.299 btags += ' ' * lb
2025-07-02 04:52:32.299 else:
2025-07-02 04:52:32.299 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.299 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.299 else:
2025-07-02 04:52:32.299 # the synch pair is identical
2025-07-02 04:52:32.299 yield ' ' + aelt
2025-07-02 04:52:32.299
2025-07-02 04:52:32.299 # pump out diffs from after the synch point
2025-07-02 04:52:32.299 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.299
2025-07-02 04:52:32.299 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.300 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.300
2025-07-02 04:52:32.300 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.300 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.300 alo = 202, ahi = 1101
2025-07-02 04:52:32.300 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.300 blo = 202, bhi = 1101
2025-07-02 04:52:32.300
2025-07-02 04:52:32.300 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.300 g = []
2025-07-02 04:52:32.300 if alo < ahi:
2025-07-02 04:52:32.300 if blo < bhi:
2025-07-02 04:52:32.300 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.300 else:
2025-07-02 04:52:32.300 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.300 elif blo < bhi:
2025-07-02 04:52:32.300 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.300
2025-07-02 04:52:32.300 > yield from g
2025-07-02 04:52:32.301
2025-07-02 04:52:32.301 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.301 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.301
2025-07-02 04:52:32.301 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.301 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.301 alo = 202, ahi = 1101
2025-07-02 04:52:32.301 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.301 blo = 202, bhi = 1101
2025-07-02 04:52:32.301
2025-07-02 04:52:32.301 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.301 r"""
2025-07-02 04:52:32.301 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.301 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.301 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.301 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.301
2025-07-02 04:52:32.301 Example:
2025-07-02 04:52:32.302
2025-07-02 04:52:32.302 >>> d = Differ()
2025-07-02 04:52:32.302 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.302 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.302 >>> print(''.join(results), end="")
2025-07-02 04:52:32.302 - abcDefghiJkl
2025-07-02 04:52:32.302 + abcdefGhijkl
2025-07-02 04:52:32.302 """
2025-07-02 04:52:32.302
2025-07-02 04:52:32.302 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.302 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.302 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.302 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.302 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.302
2025-07-02 04:52:32.302 # search for the pair that matches best without being identical
2025-07-02 04:52:32.302 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.302 # on junk -- unless we have to)
2025-07-02 04:52:32.302 for j in range(blo, bhi):
2025-07-02 04:52:32.302 bj = b[j]
2025-07-02 04:52:32.303 cruncher.set_seq2(bj)
2025-07-02 04:52:32.303 for i in range(alo, ahi):
2025-07-02 04:52:32.303 ai = a[i]
2025-07-02 04:52:32.303 if ai == bj:
2025-07-02 04:52:32.303 if eqi is None:
2025-07-02 04:52:32.303 eqi, eqj = i, j
2025-07-02 04:52:32.303 continue
2025-07-02 04:52:32.303 cruncher.set_seq1(ai)
2025-07-02 04:52:32.303 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.303 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.303 # compares by a factor of 3.
2025-07-02 04:52:32.303 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.303 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.303 # of the computation is cached by cruncher
2025-07-02 04:52:32.303 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.303 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.303 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.303 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.303 if best_ratio < cutoff:
2025-07-02 04:52:32.303 # no non-identical "pretty close" pair
2025-07-02 04:52:32.303 if eqi is None:
2025-07-02 04:52:32.304 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.304 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.304 return
2025-07-02 04:52:32.304 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.304 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.304 else:
2025-07-02 04:52:32.304 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.304 eqi = None
2025-07-02 04:52:32.304
2025-07-02 04:52:32.304 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.304 # identical
2025-07-02 04:52:32.304
2025-07-02 04:52:32.304 # pump out diffs from before the synch point
2025-07-02 04:52:32.304 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.304
2025-07-02 04:52:32.304 # do intraline marking on the synch pair
2025-07-02 04:52:32.304 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.304 if eqi is None:
2025-07-02 04:52:32.304 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.304 atags = btags = ""
2025-07-02 04:52:32.304 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.305 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.305 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.305 if tag == 'replace':
2025-07-02 04:52:32.305 atags += '^' * la
2025-07-02 04:52:32.305 btags += '^' * lb
2025-07-02 04:52:32.305 elif tag == 'delete':
2025-07-02 04:52:32.305 atags += '-' * la
2025-07-02 04:52:32.305 elif tag == 'insert':
2025-07-02 04:52:32.305 btags += '+' * lb
2025-07-02 04:52:32.305 elif tag == 'equal':
2025-07-02 04:52:32.305 atags += ' ' * la
2025-07-02 04:52:32.305 btags += ' ' * lb
2025-07-02 04:52:32.305 else:
2025-07-02 04:52:32.305 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.305 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.305 else:
2025-07-02 04:52:32.305 # the synch pair is identical
2025-07-02 04:52:32.305 yield ' ' + aelt
2025-07-02 04:52:32.305
2025-07-02 04:52:32.305 # pump out diffs from after the synch point
2025-07-02 04:52:32.305 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.305
2025-07-02 04:52:32.306 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.306 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.306
2025-07-02 04:52:32.306 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.306 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.306 alo = 203, ahi = 1101
2025-07-02 04:52:32.306 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.306 blo = 203, bhi = 1101
2025-07-02 04:52:32.306
2025-07-02 04:52:32.306 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.306 g = []
2025-07-02 04:52:32.306 if alo < ahi:
2025-07-02 04:52:32.306 if blo < bhi:
2025-07-02 04:52:32.306 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.306 else:
2025-07-02 04:52:32.306 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.306 elif blo < bhi:
2025-07-02 04:52:32.306 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.306
2025-07-02 04:52:32.306 > yield from g
2025-07-02 04:52:32.306
2025-07-02 04:52:32.307 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.307 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.307
2025-07-02 04:52:32.307 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.307 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.307 alo = 203, ahi = 1101
2025-07-02 04:52:32.307 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.307 blo = 203, bhi = 1101
2025-07-02 04:52:32.307
2025-07-02 04:52:32.307 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.307 r"""
2025-07-02 04:52:32.307 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.307 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.307 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.307 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.307
2025-07-02 04:52:32.307 Example:
2025-07-02 04:52:32.307
2025-07-02 04:52:32.307 >>> d = Differ()
2025-07-02 04:52:32.307 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.307 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.308 >>> print(''.join(results), end="")
2025-07-02 04:52:32.308 - abcDefghiJkl
2025-07-02 04:52:32.308 + abcdefGhijkl
2025-07-02 04:52:32.308 """
2025-07-02 04:52:32.308
2025-07-02 04:52:32.308 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.308 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.308 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.308 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.308 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.308
2025-07-02 04:52:32.308 # search for the pair that matches best without being identical
2025-07-02 04:52:32.308 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.308 # on junk -- unless we have to)
2025-07-02 04:52:32.308 for j in range(blo, bhi):
2025-07-02 04:52:32.308 bj = b[j]
2025-07-02 04:52:32.308 cruncher.set_seq2(bj)
2025-07-02 04:52:32.309 for i in range(alo, ahi):
2025-07-02 04:52:32.309 ai = a[i]
2025-07-02 04:52:32.309 if ai == bj:
2025-07-02 04:52:32.309 if eqi is None:
2025-07-02 04:52:32.309 eqi, eqj = i, j
2025-07-02 04:52:32.309 continue
2025-07-02 04:52:32.309 cruncher.set_seq1(ai)
2025-07-02 04:52:32.309 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.309 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.309 # compares by a factor of 3.
2025-07-02 04:52:32.309 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.309 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.309 # of the computation is cached by cruncher
2025-07-02 04:52:32.309 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.309 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.309 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.309 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.309 if best_ratio < cutoff:
2025-07-02 04:52:32.309 # no non-identical "pretty close" pair
2025-07-02 04:52:32.309 if eqi is None:
2025-07-02 04:52:32.310 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.310 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.310 return
2025-07-02 04:52:32.310 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.310 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.310 else:
2025-07-02 04:52:32.310 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.310 eqi = None
2025-07-02 04:52:32.310
2025-07-02 04:52:32.310 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.310 # identical
2025-07-02 04:52:32.310
2025-07-02 04:52:32.310 # pump out diffs from before the synch point
2025-07-02 04:52:32.310 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.310
2025-07-02 04:52:32.310 # do intraline marking on the synch pair
2025-07-02 04:52:32.310 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.310 if eqi is None:
2025-07-02 04:52:32.310 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.310 atags = btags = ""
2025-07-02 04:52:32.310 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.311 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.311 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.311 if tag == 'replace':
2025-07-02 04:52:32.311 atags += '^' * la
2025-07-02 04:52:32.311 btags += '^' * lb
2025-07-02 04:52:32.311 elif tag == 'delete':
2025-07-02 04:52:32.311 atags += '-' * la
2025-07-02 04:52:32.311 elif tag == 'insert':
2025-07-02 04:52:32.311 btags += '+' * lb
2025-07-02 04:52:32.311 elif tag == 'equal':
2025-07-02 04:52:32.311 atags += ' ' * la
2025-07-02 04:52:32.311 btags += ' ' * lb
2025-07-02 04:52:32.311 else:
2025-07-02 04:52:32.311 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.311 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.311 else:
2025-07-02 04:52:32.311 # the synch pair is identical
2025-07-02 04:52:32.311 yield ' ' + aelt
2025-07-02 04:52:32.311
2025-07-02 04:52:32.311 # pump out diffs from after the synch point
2025-07-02 04:52:32.311 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.312
2025-07-02 04:52:32.312 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.312 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.312
2025-07-02 04:52:32.312 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.312 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.312 alo = 204, ahi = 1101
2025-07-02 04:52:32.312 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.312 blo = 204, bhi = 1101
2025-07-02 04:52:32.312
2025-07-02 04:52:32.312 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.312 g = []
2025-07-02 04:52:32.312 if alo < ahi:
2025-07-02 04:52:32.312 if blo < bhi:
2025-07-02 04:52:32.312 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.312 else:
2025-07-02 04:52:32.312 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.312 elif blo < bhi:
2025-07-02 04:52:32.312 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.312
2025-07-02 04:52:32.312 > yield from g
2025-07-02 04:52:32.313
2025-07-02 04:52:32.313 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.313 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.313
2025-07-02 04:52:32.313 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.313 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.313 alo = 204, ahi = 1101
2025-07-02 04:52:32.313 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.313 blo = 204, bhi = 1101
2025-07-02 04:52:32.313
2025-07-02 04:52:32.313 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.313 r"""
2025-07-02 04:52:32.313 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.313 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.313 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.313 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.313
2025-07-02 04:52:32.313 Example:
2025-07-02 04:52:32.313
2025-07-02 04:52:32.313 >>> d = Differ()
2025-07-02 04:52:32.313 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.313 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.314 >>> print(''.join(results), end="")
2025-07-02 04:52:32.314 - abcDefghiJkl
2025-07-02 04:52:32.314 + abcdefGhijkl
2025-07-02 04:52:32.314 """
2025-07-02 04:52:32.314
2025-07-02 04:52:32.314 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.314 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.314 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.314 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.314 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.314
2025-07-02 04:52:32.314 # search for the pair that matches best without being identical
2025-07-02 04:52:32.314 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.314 # on junk -- unless we have to)
2025-07-02 04:52:32.314 for j in range(blo, bhi):
2025-07-02 04:52:32.314 bj = b[j]
2025-07-02 04:52:32.314 cruncher.set_seq2(bj)
2025-07-02 04:52:32.314 for i in range(alo, ahi):
2025-07-02 04:52:32.314 ai = a[i]
2025-07-02 04:52:32.315 if ai == bj:
2025-07-02 04:52:32.315 if eqi is None:
2025-07-02 04:52:32.315 eqi, eqj = i, j
2025-07-02 04:52:32.315 continue
2025-07-02 04:52:32.315 cruncher.set_seq1(ai)
2025-07-02 04:52:32.315 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.315 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.315 # compares by a factor of 3.
2025-07-02 04:52:32.315 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.315 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.315 # of the computation is cached by cruncher
2025-07-02 04:52:32.315 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.315 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.315 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.315 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.315 if best_ratio < cutoff:
2025-07-02 04:52:32.315 # no non-identical "pretty close" pair
2025-07-02 04:52:32.315 if eqi is None:
2025-07-02 04:52:32.315 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.315 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.315 return
2025-07-02 04:52:32.315 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.316 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.316 else:
2025-07-02 04:52:32.316 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.316 eqi = None
2025-07-02 04:52:32.316
2025-07-02 04:52:32.316 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.316 # identical
2025-07-02 04:52:32.316
2025-07-02 04:52:32.316 # pump out diffs from before the synch point
2025-07-02 04:52:32.316 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.316
2025-07-02 04:52:32.316 # do intraline marking on the synch pair
2025-07-02 04:52:32.316 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.316 if eqi is None:
2025-07-02 04:52:32.316 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.316 atags = btags = ""
2025-07-02 04:52:32.316 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.316 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.316 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.317 if tag == 'replace':
2025-07-02 04:52:32.317 atags += '^' * la
2025-07-02 04:52:32.317 btags += '^' * lb
2025-07-02 04:52:32.317 elif tag == 'delete':
2025-07-02 04:52:32.317 atags += '-' * la
2025-07-02 04:52:32.317 elif tag == 'insert':
2025-07-02 04:52:32.317 btags += '+' * lb
2025-07-02 04:52:32.317 elif tag == 'equal':
2025-07-02 04:52:32.317 atags += ' ' * la
2025-07-02 04:52:32.317 btags += ' ' * lb
2025-07-02 04:52:32.317 else:
2025-07-02 04:52:32.317 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.317 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.317 else:
2025-07-02 04:52:32.317 # the synch pair is identical
2025-07-02 04:52:32.317 yield ' ' + aelt
2025-07-02 04:52:32.317
2025-07-02 04:52:32.317 # pump out diffs from after the synch point
2025-07-02 04:52:32.317 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.317
2025-07-02 04:52:32.317 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.318 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.318
2025-07-02 04:52:32.318 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.318 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.318 alo = 205, ahi = 1101
2025-07-02 04:52:32.318 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.318 blo = 205, bhi = 1101
2025-07-02 04:52:32.318
2025-07-02 04:52:32.318 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.318 g = []
2025-07-02 04:52:32.318 if alo < ahi:
2025-07-02 04:52:32.318 if blo < bhi:
2025-07-02 04:52:32.318 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.318 else:
2025-07-02 04:52:32.318 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.318 elif blo < bhi:
2025-07-02 04:52:32.318 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.318
2025-07-02 04:52:32.318 > yield from g
2025-07-02 04:52:32.318
2025-07-02 04:52:32.319 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.319 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.319
2025-07-02 04:52:32.319 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.319 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.319 alo = 205, ahi = 1101
2025-07-02 04:52:32.319 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.319 blo = 205, bhi = 1101
2025-07-02 04:52:32.319
2025-07-02 04:52:32.319 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.319 r"""
2025-07-02 04:52:32.319 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.319 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.319 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.319 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.319
2025-07-02 04:52:32.319 Example:
2025-07-02 04:52:32.319
2025-07-02 04:52:32.319 >>> d = Differ()
2025-07-02 04:52:32.319 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.319 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.320 >>> print(''.join(results), end="")
2025-07-02 04:52:32.320 - abcDefghiJkl
2025-07-02 04:52:32.320 + abcdefGhijkl
2025-07-02 04:52:32.320 """
2025-07-02 04:52:32.320
2025-07-02 04:52:32.320 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.320 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.320 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.320 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.320 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.320
2025-07-02 04:52:32.320 # search for the pair that matches best without being identical
2025-07-02 04:52:32.320 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.320 # on junk -- unless we have to)
2025-07-02 04:52:32.320 for j in range(blo, bhi):
2025-07-02 04:52:32.320 bj = b[j]
2025-07-02 04:52:32.320 cruncher.set_seq2(bj)
2025-07-02 04:52:32.320 for i in range(alo, ahi):
2025-07-02 04:52:32.320 ai = a[i]
2025-07-02 04:52:32.320 if ai == bj:
2025-07-02 04:52:32.321 if eqi is None:
2025-07-02 04:52:32.321 eqi, eqj = i, j
2025-07-02 04:52:32.321 continue
2025-07-02 04:52:32.321 cruncher.set_seq1(ai)
2025-07-02 04:52:32.321 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.321 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.321 # compares by a factor of 3.
2025-07-02 04:52:32.321 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.321 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.321 # of the computation is cached by cruncher
2025-07-02 04:52:32.321 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.321 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.321 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.321 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.321 if best_ratio < cutoff:
2025-07-02 04:52:32.321 # no non-identical "pretty close" pair
2025-07-02 04:52:32.321 if eqi is None:
2025-07-02 04:52:32.321 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.321 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.321 return
2025-07-02 04:52:32.321 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.322 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.322 else:
2025-07-02 04:52:32.322 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.322 eqi = None
2025-07-02 04:52:32.322
2025-07-02 04:52:32.322 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.322 # identical
2025-07-02 04:52:32.322
2025-07-02 04:52:32.322 # pump out diffs from before the synch point
2025-07-02 04:52:32.322 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.322
2025-07-02 04:52:32.322 # do intraline marking on the synch pair
2025-07-02 04:52:32.322 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.322 if eqi is None:
2025-07-02 04:52:32.322 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.322 atags = btags = ""
2025-07-02 04:52:32.322 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.322 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.322 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.322 if tag == 'replace':
2025-07-02 04:52:32.322 atags += '^' * la
2025-07-02 04:52:32.322 btags += '^' * lb
2025-07-02 04:52:32.323 elif tag == 'delete':
2025-07-02 04:52:32.323 atags += '-' * la
2025-07-02 04:52:32.323 elif tag == 'insert':
2025-07-02 04:52:32.323 btags += '+' * lb
2025-07-02 04:52:32.323 elif tag == 'equal':
2025-07-02 04:52:32.323 atags += ' ' * la
2025-07-02 04:52:32.323 btags += ' ' * lb
2025-07-02 04:52:32.323 else:
2025-07-02 04:52:32.323 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.323 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.323 else:
2025-07-02 04:52:32.323 # the synch pair is identical
2025-07-02 04:52:32.323 yield ' ' + aelt
2025-07-02 04:52:32.323
2025-07-02 04:52:32.323 # pump out diffs from after the synch point
2025-07-02 04:52:32.323 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.323
2025-07-02 04:52:32.323 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.323 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.323
2025-07-02 04:52:32.323 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.324 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.324 alo = 206, ahi = 1101
2025-07-02 04:52:32.324 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.324 blo = 206, bhi = 1101
2025-07-02 04:52:32.324
2025-07-02 04:52:32.324 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.324 g = []
2025-07-02 04:52:32.324 if alo < ahi:
2025-07-02 04:52:32.324 if blo < bhi:
2025-07-02 04:52:32.324 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.324 else:
2025-07-02 04:52:32.324 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.324 elif blo < bhi:
2025-07-02 04:52:32.324 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.324
2025-07-02 04:52:32.324 > yield from g
2025-07-02 04:52:32.324
2025-07-02 04:52:32.324 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.324 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.324
2025-07-02 04:52:32.325 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.325 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.325 alo = 206, ahi = 1101
2025-07-02 04:52:32.325 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.325 blo = 206, bhi = 1101
2025-07-02 04:52:32.325
2025-07-02 04:52:32.325 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.325 r"""
2025-07-02 04:52:32.325 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.325 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.325 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.325 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.325
2025-07-02 04:52:32.325 Example:
2025-07-02 04:52:32.325
2025-07-02 04:52:32.325 >>> d = Differ()
2025-07-02 04:52:32.325 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.325 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.325 >>> print(''.join(results), end="")
2025-07-02 04:52:32.325 - abcDefghiJkl
2025-07-02 04:52:32.326 + abcdefGhijkl
2025-07-02 04:52:32.326 """
2025-07-02 04:52:32.326
2025-07-02 04:52:32.326 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.326 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.326 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.326 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.326 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.326
2025-07-02 04:52:32.326 # search for the pair that matches best without being identical
2025-07-02 04:52:32.326 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.326 # on junk -- unless we have to)
2025-07-02 04:52:32.326 for j in range(blo, bhi):
2025-07-02 04:52:32.326 bj = b[j]
2025-07-02 04:52:32.326 cruncher.set_seq2(bj)
2025-07-02 04:52:32.326 for i in range(alo, ahi):
2025-07-02 04:52:32.326 ai = a[i]
2025-07-02 04:52:32.326 if ai == bj:
2025-07-02 04:52:32.326 if eqi is None:
2025-07-02 04:52:32.327 eqi, eqj = i, j
2025-07-02 04:52:32.327 continue
2025-07-02 04:52:32.327 cruncher.set_seq1(ai)
2025-07-02 04:52:32.327 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.327 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.327 # compares by a factor of 3.
2025-07-02 04:52:32.327 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.327 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.327 # of the computation is cached by cruncher
2025-07-02 04:52:32.327 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.327 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.327 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.327 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.327 if best_ratio < cutoff:
2025-07-02 04:52:32.327 # no non-identical "pretty close" pair
2025-07-02 04:52:32.327 if eqi is None:
2025-07-02 04:52:32.327 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.327 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.327 return
2025-07-02 04:52:32.327 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.327 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.328 else:
2025-07-02 04:52:32.328 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.328 eqi = None
2025-07-02 04:52:32.328
2025-07-02 04:52:32.328 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.328 # identical
2025-07-02 04:52:32.328
2025-07-02 04:52:32.328 # pump out diffs from before the synch point
2025-07-02 04:52:32.328 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.328
2025-07-02 04:52:32.328 # do intraline marking on the synch pair
2025-07-02 04:52:32.328 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.328 if eqi is None:
2025-07-02 04:52:32.328 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.328 atags = btags = ""
2025-07-02 04:52:32.328 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.328 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.328 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.328 if tag == 'replace':
2025-07-02 04:52:32.328 atags += '^' * la
2025-07-02 04:52:32.328 btags += '^' * lb
2025-07-02 04:52:32.329 elif tag == 'delete':
2025-07-02 04:52:32.329 atags += '-' * la
2025-07-02 04:52:32.329 elif tag == 'insert':
2025-07-02 04:52:32.329 btags += '+' * lb
2025-07-02 04:52:32.329 elif tag == 'equal':
2025-07-02 04:52:32.329 atags += ' ' * la
2025-07-02 04:52:32.329 btags += ' ' * lb
2025-07-02 04:52:32.329 else:
2025-07-02 04:52:32.329 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.329 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.329 else:
2025-07-02 04:52:32.329 # the synch pair is identical
2025-07-02 04:52:32.329 yield ' ' + aelt
2025-07-02 04:52:32.329
2025-07-02 04:52:32.329 # pump out diffs from after the synch point
2025-07-02 04:52:32.329 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.329
2025-07-02 04:52:32.329 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.329 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.329
2025-07-02 04:52:32.329 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.329 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.330 alo = 207, ahi = 1101
2025-07-02 04:52:32.330 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.330 blo = 207, bhi = 1101
2025-07-02 04:52:32.330
2025-07-02 04:52:32.330 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.330 g = []
2025-07-02 04:52:32.330 if alo < ahi:
2025-07-02 04:52:32.330 if blo < bhi:
2025-07-02 04:52:32.330 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.330 else:
2025-07-02 04:52:32.330 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.330 elif blo < bhi:
2025-07-02 04:52:32.330 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.330
2025-07-02 04:52:32.330 > yield from g
2025-07-02 04:52:32.330
2025-07-02 04:52:32.330 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.330 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.330
2025-07-02 04:52:32.330 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.330 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.331 alo = 207, ahi = 1101
2025-07-02 04:52:32.331 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.331 blo = 207, bhi = 1101
2025-07-02 04:52:32.331
2025-07-02 04:52:32.331 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.331 r"""
2025-07-02 04:52:32.331 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.331 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.331 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.331 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.331
2025-07-02 04:52:32.331 Example:
2025-07-02 04:52:32.331
2025-07-02 04:52:32.331 >>> d = Differ()
2025-07-02 04:52:32.331 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.331 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.331 >>> print(''.join(results), end="")
2025-07-02 04:52:32.331 - abcDefghiJkl
2025-07-02 04:52:32.331 + abcdefGhijkl
2025-07-02 04:52:32.332 """
2025-07-02 04:52:32.332
2025-07-02 04:52:32.332 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.332 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.332 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.332 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.332 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.332
2025-07-02 04:52:32.332 # search for the pair that matches best without being identical
2025-07-02 04:52:32.332 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.332 # on junk -- unless we have to)
2025-07-02 04:52:32.332 for j in range(blo, bhi):
2025-07-02 04:52:32.332 bj = b[j]
2025-07-02 04:52:32.332 cruncher.set_seq2(bj)
2025-07-02 04:52:32.332 for i in range(alo, ahi):
2025-07-02 04:52:32.332 ai = a[i]
2025-07-02 04:52:32.332 if ai == bj:
2025-07-02 04:52:32.332 if eqi is None:
2025-07-02 04:52:32.332 eqi, eqj = i, j
2025-07-02 04:52:32.332 continue
2025-07-02 04:52:32.332 cruncher.set_seq1(ai)
2025-07-02 04:52:32.332 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.333 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.333 # compares by a factor of 3.
2025-07-02 04:52:32.333 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.333 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.333 # of the computation is cached by cruncher
2025-07-02 04:52:32.333 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.333 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.333 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.333 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.333 if best_ratio < cutoff:
2025-07-02 04:52:32.333 # no non-identical "pretty close" pair
2025-07-02 04:52:32.333 if eqi is None:
2025-07-02 04:52:32.333 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.333 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.333 return
2025-07-02 04:52:32.333 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.333 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.333 else:
2025-07-02 04:52:32.333 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.334 eqi = None
2025-07-02 04:52:32.334
2025-07-02 04:52:32.334 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.334 # identical
2025-07-02 04:52:32.334
2025-07-02 04:52:32.334 # pump out diffs from before the synch point
2025-07-02 04:52:32.334 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.334
2025-07-02 04:52:32.334 # do intraline marking on the synch pair
2025-07-02 04:52:32.334 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.334 if eqi is None:
2025-07-02 04:52:32.334 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.334 atags = btags = ""
2025-07-02 04:52:32.334 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.334 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.334 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.334 if tag == 'replace':
2025-07-02 04:52:32.334 atags += '^' * la
2025-07-02 04:52:32.334 btags += '^' * lb
2025-07-02 04:52:32.334 elif tag == 'delete':
2025-07-02 04:52:32.334 atags += '-' * la
2025-07-02 04:52:32.335 elif tag == 'insert':
2025-07-02 04:52:32.335 btags += '+' * lb
2025-07-02 04:52:32.335 elif tag == 'equal':
2025-07-02 04:52:32.335 atags += ' ' * la
2025-07-02 04:52:32.335 btags += ' ' * lb
2025-07-02 04:52:32.335 else:
2025-07-02 04:52:32.335 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.335 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.335 else:
2025-07-02 04:52:32.335 # the synch pair is identical
2025-07-02 04:52:32.335 yield ' ' + aelt
2025-07-02 04:52:32.335
2025-07-02 04:52:32.335 # pump out diffs from after the synch point
2025-07-02 04:52:32.335 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.335
2025-07-02 04:52:32.335 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.335 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.335
2025-07-02 04:52:32.335 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.335 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.335 alo = 208, ahi = 1101
2025-07-02 04:52:32.336 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.336 blo = 208, bhi = 1101
2025-07-02 04:52:32.336
2025-07-02 04:52:32.336 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.336 g = []
2025-07-02 04:52:32.336 if alo < ahi:
2025-07-02 04:52:32.336 if blo < bhi:
2025-07-02 04:52:32.336 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.336 else:
2025-07-02 04:52:32.336 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.336 elif blo < bhi:
2025-07-02 04:52:32.336 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.336
2025-07-02 04:52:32.336 > yield from g
2025-07-02 04:52:32.336
2025-07-02 04:52:32.336 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.336 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.336
2025-07-02 04:52:32.336 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.336 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.336 alo = 208, ahi = 1101
2025-07-02 04:52:32.336 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.337 blo = 208, bhi = 1101
2025-07-02 04:52:32.337
2025-07-02 04:52:32.337 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.337 r"""
2025-07-02 04:52:32.337 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.337 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.337 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.337 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.337
2025-07-02 04:52:32.337 Example:
2025-07-02 04:52:32.337
2025-07-02 04:52:32.337 >>> d = Differ()
2025-07-02 04:52:32.337 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.337 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.337 >>> print(''.join(results), end="")
2025-07-02 04:52:32.337 - abcDefghiJkl
2025-07-02 04:52:32.337 + abcdefGhijkl
2025-07-02 04:52:32.337 """
2025-07-02 04:52:32.337
2025-07-02 04:52:32.338 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.338 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.338 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.338 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.338 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.338
2025-07-02 04:52:32.338 # search for the pair that matches best without being identical
2025-07-02 04:52:32.338 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.338 # on junk -- unless we have to)
2025-07-02 04:52:32.338 for j in range(blo, bhi):
2025-07-02 04:52:32.338 bj = b[j]
2025-07-02 04:52:32.338 cruncher.set_seq2(bj)
2025-07-02 04:52:32.338 for i in range(alo, ahi):
2025-07-02 04:52:32.338 ai = a[i]
2025-07-02 04:52:32.338 if ai == bj:
2025-07-02 04:52:32.338 if eqi is None:
2025-07-02 04:52:32.338 eqi, eqj = i, j
2025-07-02 04:52:32.338 continue
2025-07-02 04:52:32.338 cruncher.set_seq1(ai)
2025-07-02 04:52:32.338 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.338 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.338 # compares by a factor of 3.
2025-07-02 04:52:32.339 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.339 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.339 # of the computation is cached by cruncher
2025-07-02 04:52:32.339 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.339 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.339 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.339 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.339 if best_ratio < cutoff:
2025-07-02 04:52:32.339 # no non-identical "pretty close" pair
2025-07-02 04:52:32.339 if eqi is None:
2025-07-02 04:52:32.339 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.339 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.339 return
2025-07-02 04:52:32.339 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.339 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.339 else:
2025-07-02 04:52:32.339 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.339 eqi = None
2025-07-02 04:52:32.339
2025-07-02 04:52:32.339 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.339 # identical
2025-07-02 04:52:32.340
2025-07-02 04:52:32.340 # pump out diffs from before the synch point
2025-07-02 04:52:32.340 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.340
2025-07-02 04:52:32.340 # do intraline marking on the synch pair
2025-07-02 04:52:32.340 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.340 if eqi is None:
2025-07-02 04:52:32.340 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.340 atags = btags = ""
2025-07-02 04:52:32.340 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.340 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.340 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.340 if tag == 'replace':
2025-07-02 04:52:32.340 atags += '^' * la
2025-07-02 04:52:32.340 btags += '^' * lb
2025-07-02 04:52:32.340 elif tag == 'delete':
2025-07-02 04:52:32.340 atags += '-' * la
2025-07-02 04:52:32.340 elif tag == 'insert':
2025-07-02 04:52:32.341 btags += '+' * lb
2025-07-02 04:52:32.341 elif tag == 'equal':
2025-07-02 04:52:32.341 atags += ' ' * la
2025-07-02 04:52:32.341 btags += ' ' * lb
2025-07-02 04:52:32.341 else:
2025-07-02 04:52:32.341 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.341 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.341 else:
2025-07-02 04:52:32.341 # the synch pair is identical
2025-07-02 04:52:32.341 yield ' ' + aelt
2025-07-02 04:52:32.341
2025-07-02 04:52:32.341 # pump out diffs from after the synch point
2025-07-02 04:52:32.341 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.341
2025-07-02 04:52:32.341 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.341 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.341
2025-07-02 04:52:32.341 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.342 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.342 alo = 209, ahi = 1101
2025-07-02 04:52:32.342 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.342 blo = 209, bhi = 1101
2025-07-02 04:52:32.342
2025-07-02 04:52:32.342 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.342 g = []
2025-07-02 04:52:32.342 if alo < ahi:
2025-07-02 04:52:32.342 if blo < bhi:
2025-07-02 04:52:32.342 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.342 else:
2025-07-02 04:52:32.342 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.342 elif blo < bhi:
2025-07-02 04:52:32.342 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.342
2025-07-02 04:52:32.342 > yield from g
2025-07-02 04:52:32.342
2025-07-02 04:52:32.342 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.342 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.343
2025-07-02 04:52:32.343 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.343 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.343 alo = 209, ahi = 1101
2025-07-02 04:52:32.343 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.343 blo = 209, bhi = 1101
2025-07-02 04:52:32.343
2025-07-02 04:52:32.343 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.343 r"""
2025-07-02 04:52:32.343 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.343 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.343 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.343 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.343
2025-07-02 04:52:32.343 Example:
2025-07-02 04:52:32.343
2025-07-02 04:52:32.343 >>> d = Differ()
2025-07-02 04:52:32.343 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.344 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.344 >>> print(''.join(results), end="")
2025-07-02 04:52:32.344 - abcDefghiJkl
2025-07-02 04:52:32.344 + abcdefGhijkl
2025-07-02 04:52:32.344 """
2025-07-02 04:52:32.344
2025-07-02 04:52:32.344 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.344 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.344 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.344 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.344 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.344
2025-07-02 04:52:32.344 # search for the pair that matches best without being identical
2025-07-02 04:52:32.344 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.344 # on junk -- unless we have to)
2025-07-02 04:52:32.344 for j in range(blo, bhi):
2025-07-02 04:52:32.344 bj = b[j]
2025-07-02 04:52:32.344 cruncher.set_seq2(bj)
2025-07-02 04:52:32.345 for i in range(alo, ahi):
2025-07-02 04:52:32.345 ai = a[i]
2025-07-02 04:52:32.345 if ai == bj:
2025-07-02 04:52:32.345 if eqi is None:
2025-07-02 04:52:32.345 eqi, eqj = i, j
2025-07-02 04:52:32.345 continue
2025-07-02 04:52:32.345 cruncher.set_seq1(ai)
2025-07-02 04:52:32.345 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.345 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.345 # compares by a factor of 3.
2025-07-02 04:52:32.345 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.345 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.345 # of the computation is cached by cruncher
2025-07-02 04:52:32.345 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.345 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.345 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.345 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.345 if best_ratio < cutoff:
2025-07-02 04:52:32.345 # no non-identical "pretty close" pair
2025-07-02 04:52:32.346 if eqi is None:
2025-07-02 04:52:32.346 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.346 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.346 return
2025-07-02 04:52:32.346 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.346 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.346 else:
2025-07-02 04:52:32.346 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.346 eqi = None
2025-07-02 04:52:32.346
2025-07-02 04:52:32.346 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.346 # identical
2025-07-02 04:52:32.346
2025-07-02 04:52:32.346 # pump out diffs from before the synch point
2025-07-02 04:52:32.346 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.346
2025-07-02 04:52:32.346 # do intraline marking on the synch pair
2025-07-02 04:52:32.346 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.346 if eqi is None:
2025-07-02 04:52:32.346 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.346 atags = btags = ""
2025-07-02 04:52:32.347 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.347 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.347 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.347 if tag == 'replace':
2025-07-02 04:52:32.347 atags += '^' * la
2025-07-02 04:52:32.347 btags += '^' * lb
2025-07-02 04:52:32.347 elif tag == 'delete':
2025-07-02 04:52:32.347 atags += '-' * la
2025-07-02 04:52:32.347 elif tag == 'insert':
2025-07-02 04:52:32.347 btags += '+' * lb
2025-07-02 04:52:32.347 elif tag == 'equal':
2025-07-02 04:52:32.347 atags += ' ' * la
2025-07-02 04:52:32.347 btags += ' ' * lb
2025-07-02 04:52:32.347 else:
2025-07-02 04:52:32.347 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.347 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.347 else:
2025-07-02 04:52:32.347 # the synch pair is identical
2025-07-02 04:52:32.347 yield ' ' + aelt
2025-07-02 04:52:32.347
2025-07-02 04:52:32.348 # pump out diffs from after the synch point
2025-07-02 04:52:32.348 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.348
2025-07-02 04:52:32.348 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.348 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.348
2025-07-02 04:52:32.348 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.348 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.348 alo = 210, ahi = 1101
2025-07-02 04:52:32.348 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.348 blo = 210, bhi = 1101
2025-07-02 04:52:32.348
2025-07-02 04:52:32.348 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.348 g = []
2025-07-02 04:52:32.348 if alo < ahi:
2025-07-02 04:52:32.348 if blo < bhi:
2025-07-02 04:52:32.348 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.348 else:
2025-07-02 04:52:32.348 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.348 elif blo < bhi:
2025-07-02 04:52:32.349 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.349
2025-07-02 04:52:32.349 > yield from g
2025-07-02 04:52:32.349
2025-07-02 04:52:32.349 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.349 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.349
2025-07-02 04:52:32.349 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.349 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.349 alo = 210, ahi = 1101
2025-07-02 04:52:32.349 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.349 blo = 210, bhi = 1101
2025-07-02 04:52:32.349
2025-07-02 04:52:32.349 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.349 r"""
2025-07-02 04:52:32.349 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.349 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.349 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.349 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.350
2025-07-02 04:52:32.350 Example:
2025-07-02 04:52:32.350
2025-07-02 04:52:32.350 >>> d = Differ()
2025-07-02 04:52:32.350 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.350 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.350 >>> print(''.join(results), end="")
2025-07-02 04:52:32.350 - abcDefghiJkl
2025-07-02 04:52:32.350 + abcdefGhijkl
2025-07-02 04:52:32.350 """
2025-07-02 04:52:32.350
2025-07-02 04:52:32.350 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.350 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.350 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.350 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.350 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.350
2025-07-02 04:52:32.351 # search for the pair that matches best without being identical
2025-07-02 04:52:32.351 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.351 # on junk -- unless we have to)
2025-07-02 04:52:32.351 for j in range(blo, bhi):
2025-07-02 04:52:32.351 bj = b[j]
2025-07-02 04:52:32.351 cruncher.set_seq2(bj)
2025-07-02 04:52:32.351 for i in range(alo, ahi):
2025-07-02 04:52:32.351 ai = a[i]
2025-07-02 04:52:32.351 if ai == bj:
2025-07-02 04:52:32.351 if eqi is None:
2025-07-02 04:52:32.351 eqi, eqj = i, j
2025-07-02 04:52:32.351 continue
2025-07-02 04:52:32.351 cruncher.set_seq1(ai)
2025-07-02 04:52:32.351 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.351 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.351 # compares by a factor of 3.
2025-07-02 04:52:32.351 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.351 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.351 # of the computation is cached by cruncher
2025-07-02 04:52:32.351 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.352 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.352 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.352 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.352 if best_ratio < cutoff:
2025-07-02 04:52:32.352 # no non-identical "pretty close" pair
2025-07-02 04:52:32.352 if eqi is None:
2025-07-02 04:52:32.352 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.352 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.352 return
2025-07-02 04:52:32.352 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.352 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.352 else:
2025-07-02 04:52:32.352 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.352 eqi = None
2025-07-02 04:52:32.352
2025-07-02 04:52:32.352 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.352 # identical
2025-07-02 04:52:32.352
2025-07-02 04:52:32.352 # pump out diffs from before the synch point
2025-07-02 04:52:32.352 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.352
2025-07-02 04:52:32.353 # do intraline marking on the synch pair
2025-07-02 04:52:32.353 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.353 if eqi is None:
2025-07-02 04:52:32.353 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.353 atags = btags = ""
2025-07-02 04:52:32.353 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.353 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.353 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.353 if tag == 'replace':
2025-07-02 04:52:32.353 atags += '^' * la
2025-07-02 04:52:32.353 btags += '^' * lb
2025-07-02 04:52:32.353 elif tag == 'delete':
2025-07-02 04:52:32.353 atags += '-' * la
2025-07-02 04:52:32.353 elif tag == 'insert':
2025-07-02 04:52:32.353 btags += '+' * lb
2025-07-02 04:52:32.353 elif tag == 'equal':
2025-07-02 04:52:32.353 atags += ' ' * la
2025-07-02 04:52:32.353 btags += ' ' * lb
2025-07-02 04:52:32.353 else:
2025-07-02 04:52:32.353 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.353 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.353 else:
2025-07-02 04:52:32.354 # the synch pair is identical
2025-07-02 04:52:32.354 yield ' ' + aelt
2025-07-02 04:52:32.354
2025-07-02 04:52:32.354 # pump out diffs from after the synch point
2025-07-02 04:52:32.354 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.354
2025-07-02 04:52:32.354 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.354 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.354
2025-07-02 04:52:32.354 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.354 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.354 alo = 211, ahi = 1101
2025-07-02 04:52:32.354 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.354 blo = 211, bhi = 1101
2025-07-02 04:52:32.354
2025-07-02 04:52:32.354 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.354 g = []
2025-07-02 04:52:32.354 if alo < ahi:
2025-07-02 04:52:32.354 if blo < bhi:
2025-07-02 04:52:32.354 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.354 else:
2025-07-02 04:52:32.355 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.355 elif blo < bhi:
2025-07-02 04:52:32.355 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.355
2025-07-02 04:52:32.355 > yield from g
2025-07-02 04:52:32.355
2025-07-02 04:52:32.355 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.355 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.355
2025-07-02 04:52:32.355 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.355 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.355 alo = 211, ahi = 1101
2025-07-02 04:52:32.355 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.355 blo = 211, bhi = 1101
2025-07-02 04:52:32.355
2025-07-02 04:52:32.355 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.355 r"""
2025-07-02 04:52:32.355 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.355 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.355 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.355 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.355
2025-07-02 04:52:32.356 Example:
2025-07-02 04:52:32.356
2025-07-02 04:52:32.356 >>> d = Differ()
2025-07-02 04:52:32.356 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.356 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.356 >>> print(''.join(results), end="")
2025-07-02 04:52:32.356 - abcDefghiJkl
2025-07-02 04:52:32.356 + abcdefGhijkl
2025-07-02 04:52:32.356 """
2025-07-02 04:52:32.356
2025-07-02 04:52:32.356 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.356 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.356 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.356 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.356 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.356
2025-07-02 04:52:32.356 # search for the pair that matches best without being identical
2025-07-02 04:52:32.357 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.357 # on junk -- unless we have to)
2025-07-02 04:52:32.357 for j in range(blo, bhi):
2025-07-02 04:52:32.357 bj = b[j]
2025-07-02 04:52:32.357 cruncher.set_seq2(bj)
2025-07-02 04:52:32.357 for i in range(alo, ahi):
2025-07-02 04:52:32.357 ai = a[i]
2025-07-02 04:52:32.357 if ai == bj:
2025-07-02 04:52:32.357 if eqi is None:
2025-07-02 04:52:32.357 eqi, eqj = i, j
2025-07-02 04:52:32.357 continue
2025-07-02 04:52:32.357 cruncher.set_seq1(ai)
2025-07-02 04:52:32.357 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.357 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.357 # compares by a factor of 3.
2025-07-02 04:52:32.357 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.357 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.357 # of the computation is cached by cruncher
2025-07-02 04:52:32.357 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.357 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.357 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.358 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.358 if best_ratio < cutoff:
2025-07-02 04:52:32.358 # no non-identical "pretty close" pair
2025-07-02 04:52:32.358 if eqi is None:
2025-07-02 04:52:32.358 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.358 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.358 return
2025-07-02 04:52:32.358 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.358 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.358 else:
2025-07-02 04:52:32.358 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.358 eqi = None
2025-07-02 04:52:32.358
2025-07-02 04:52:32.358 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.358 # identical
2025-07-02 04:52:32.358
2025-07-02 04:52:32.358 # pump out diffs from before the synch point
2025-07-02 04:52:32.358 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.358
2025-07-02 04:52:32.358 # do intraline marking on the synch pair
2025-07-02 04:52:32.359 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.359 if eqi is None:
2025-07-02 04:52:32.359 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.359 atags = btags = ""
2025-07-02 04:52:32.359 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.359 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.359 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.359 if tag == 'replace':
2025-07-02 04:52:32.359 atags += '^' * la
2025-07-02 04:52:32.359 btags += '^' * lb
2025-07-02 04:52:32.359 elif tag == 'delete':
2025-07-02 04:52:32.359 atags += '-' * la
2025-07-02 04:52:32.359 elif tag == 'insert':
2025-07-02 04:52:32.359 btags += '+' * lb
2025-07-02 04:52:32.359 elif tag == 'equal':
2025-07-02 04:52:32.359 atags += ' ' * la
2025-07-02 04:52:32.359 btags += ' ' * lb
2025-07-02 04:52:32.359 else:
2025-07-02 04:52:32.359 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.359 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.360 else:
2025-07-02 04:52:32.360 # the synch pair is identical
2025-07-02 04:52:32.360 yield ' ' + aelt
2025-07-02 04:52:32.360
2025-07-02 04:52:32.360 # pump out diffs from after the synch point
2025-07-02 04:52:32.360 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.360
2025-07-02 04:52:32.360 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.360 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.360
2025-07-02 04:52:32.360 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.360 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.360 alo = 212, ahi = 1101
2025-07-02 04:52:32.360 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.360 blo = 212, bhi = 1101
2025-07-02 04:52:32.360
2025-07-02 04:52:32.360 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.360 g = []
2025-07-02 04:52:32.360 if alo < ahi:
2025-07-02 04:52:32.361 if blo < bhi:
2025-07-02 04:52:32.361 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.361 else:
2025-07-02 04:52:32.361 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.361 elif blo < bhi:
2025-07-02 04:52:32.361 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.361
2025-07-02 04:52:32.361 > yield from g
2025-07-02 04:52:32.361
2025-07-02 04:52:32.361 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.361 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.361
2025-07-02 04:52:32.361 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.361 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.361 alo = 212, ahi = 1101
2025-07-02 04:52:32.361 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.361 blo = 212, bhi = 1101
2025-07-02 04:52:32.361
2025-07-02 04:52:32.361 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.361 r"""
2025-07-02 04:52:32.362 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.362 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.362 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.362 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.362
2025-07-02 04:52:32.362 Example:
2025-07-02 04:52:32.362
2025-07-02 04:52:32.362 >>> d = Differ()
2025-07-02 04:52:32.362 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.362 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.362 >>> print(''.join(results), end="")
2025-07-02 04:52:32.362 - abcDefghiJkl
2025-07-02 04:52:32.362 + abcdefGhijkl
2025-07-02 04:52:32.362 """
2025-07-02 04:52:32.362
2025-07-02 04:52:32.362 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.362 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.362 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.363 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.363 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.363
2025-07-02 04:52:32.363 # search for the pair that matches best without being identical
2025-07-02 04:52:32.363 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.363 # on junk -- unless we have to)
2025-07-02 04:52:32.363 for j in range(blo, bhi):
2025-07-02 04:52:32.363 bj = b[j]
2025-07-02 04:52:32.363 cruncher.set_seq2(bj)
2025-07-02 04:52:32.363 for i in range(alo, ahi):
2025-07-02 04:52:32.363 ai = a[i]
2025-07-02 04:52:32.363 if ai == bj:
2025-07-02 04:52:32.363 if eqi is None:
2025-07-02 04:52:32.363 eqi, eqj = i, j
2025-07-02 04:52:32.363 continue
2025-07-02 04:52:32.363 cruncher.set_seq1(ai)
2025-07-02 04:52:32.363 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.363 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.363 # compares by a factor of 3.
2025-07-02 04:52:32.363 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.363 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.364 # of the computation is cached by cruncher
2025-07-02 04:52:32.364 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.364 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.364 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.364 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.364 if best_ratio < cutoff:
2025-07-02 04:52:32.364 # no non-identical "pretty close" pair
2025-07-02 04:52:32.364 if eqi is None:
2025-07-02 04:52:32.364 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.364 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.364 return
2025-07-02 04:52:32.364 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.364 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.364 else:
2025-07-02 04:52:32.364 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.364 eqi = None
2025-07-02 04:52:32.364
2025-07-02 04:52:32.364 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.364 # identical
2025-07-02 04:52:32.365
2025-07-02 04:52:32.365 # pump out diffs from before the synch point
2025-07-02 04:52:32.365 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.365
2025-07-02 04:52:32.365 # do intraline marking on the synch pair
2025-07-02 04:52:32.365 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.365 if eqi is None:
2025-07-02 04:52:32.365 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.365 atags = btags = ""
2025-07-02 04:52:32.365 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.365 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.365 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.365 if tag == 'replace':
2025-07-02 04:52:32.365 atags += '^' * la
2025-07-02 04:52:32.365 btags += '^' * lb
2025-07-02 04:52:32.365 elif tag == 'delete':
2025-07-02 04:52:32.365 atags += '-' * la
2025-07-02 04:52:32.365 elif tag == 'insert':
2025-07-02 04:52:32.365 btags += '+' * lb
2025-07-02 04:52:32.366 elif tag == 'equal':
2025-07-02 04:52:32.366 atags += ' ' * la
2025-07-02 04:52:32.366 btags += ' ' * lb
2025-07-02 04:52:32.366 else:
2025-07-02 04:52:32.366 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.366 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.366 else:
2025-07-02 04:52:32.366 # the synch pair is identical
2025-07-02 04:52:32.366 yield ' ' + aelt
2025-07-02 04:52:32.366
2025-07-02 04:52:32.366 # pump out diffs from after the synch point
2025-07-02 04:52:32.366 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.366
2025-07-02 04:52:32.366 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.366 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.366
2025-07-02 04:52:32.366 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.366 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.366 alo = 213, ahi = 1101
2025-07-02 04:52:32.367 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.367 blo = 213, bhi = 1101
2025-07-02 04:52:32.367
2025-07-02 04:52:32.367 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.367 g = []
2025-07-02 04:52:32.367 if alo < ahi:
2025-07-02 04:52:32.367 if blo < bhi:
2025-07-02 04:52:32.367 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.367 else:
2025-07-02 04:52:32.367 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.367 elif blo < bhi:
2025-07-02 04:52:32.367 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.367
2025-07-02 04:52:32.367 > yield from g
2025-07-02 04:52:32.367
2025-07-02 04:52:32.367 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.367 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.367
2025-07-02 04:52:32.367 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.367 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.368 alo = 213, ahi = 1101
2025-07-02 04:52:32.368 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.368 blo = 213, bhi = 1101
2025-07-02 04:52:32.368
2025-07-02 04:52:32.368 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.368 r"""
2025-07-02 04:52:32.368 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.368 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.368 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.368 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.368
2025-07-02 04:52:32.368 Example:
2025-07-02 04:52:32.368
2025-07-02 04:52:32.368 >>> d = Differ()
2025-07-02 04:52:32.368 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.368 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.368 >>> print(''.join(results), end="")
2025-07-02 04:52:32.368 - abcDefghiJkl
2025-07-02 04:52:32.368 + abcdefGhijkl
2025-07-02 04:52:32.369 """
2025-07-02 04:52:32.369
2025-07-02 04:52:32.369 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.369 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.369 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.369 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.369 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.369
2025-07-02 04:52:32.369 # search for the pair that matches best without being identical
2025-07-02 04:52:32.369 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.369 # on junk -- unless we have to)
2025-07-02 04:52:32.369 for j in range(blo, bhi):
2025-07-02 04:52:32.369 bj = b[j]
2025-07-02 04:52:32.369 cruncher.set_seq2(bj)
2025-07-02 04:52:32.369 for i in range(alo, ahi):
2025-07-02 04:52:32.369 ai = a[i]
2025-07-02 04:52:32.369 if ai == bj:
2025-07-02 04:52:32.369 if eqi is None:
2025-07-02 04:52:32.369 eqi, eqj = i, j
2025-07-02 04:52:32.369 continue
2025-07-02 04:52:32.369 cruncher.set_seq1(ai)
2025-07-02 04:52:32.370 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.370 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.370 # compares by a factor of 3.
2025-07-02 04:52:32.370 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.370 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.370 # of the computation is cached by cruncher
2025-07-02 04:52:32.370 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.370 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.370 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.370 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.370 if best_ratio < cutoff:
2025-07-02 04:52:32.370 # no non-identical "pretty close" pair
2025-07-02 04:52:32.370 if eqi is None:
2025-07-02 04:52:32.370 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.370 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.370 return
2025-07-02 04:52:32.370 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.370 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.370 else:
2025-07-02 04:52:32.370 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.370 eqi = None
2025-07-02 04:52:32.371
2025-07-02 04:52:32.371 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.371 # identical
2025-07-02 04:52:32.371
2025-07-02 04:52:32.371 # pump out diffs from before the synch point
2025-07-02 04:52:32.371 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.371
2025-07-02 04:52:32.371 # do intraline marking on the synch pair
2025-07-02 04:52:32.371 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.371 if eqi is None:
2025-07-02 04:52:32.371 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.371 atags = btags = ""
2025-07-02 04:52:32.371 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.371 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.371 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.371 if tag == 'replace':
2025-07-02 04:52:32.371 atags += '^' * la
2025-07-02 04:52:32.371 btags += '^' * lb
2025-07-02 04:52:32.371 elif tag == 'delete':
2025-07-02 04:52:32.371 atags += '-' * la
2025-07-02 04:52:32.371 elif tag == 'insert':
2025-07-02 04:52:32.371 btags += '+' * lb
2025-07-02 04:52:32.372 elif tag == 'equal':
2025-07-02 04:52:32.372 atags += ' ' * la
2025-07-02 04:52:32.372 btags += ' ' * lb
2025-07-02 04:52:32.372 else:
2025-07-02 04:52:32.372 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.372 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.372 else:
2025-07-02 04:52:32.372 # the synch pair is identical
2025-07-02 04:52:32.372 yield ' ' + aelt
2025-07-02 04:52:32.372
2025-07-02 04:52:32.372 # pump out diffs from after the synch point
2025-07-02 04:52:32.372 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.372
2025-07-02 04:52:32.372 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.372 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.372
2025-07-02 04:52:32.372 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.372 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.372 alo = 214, ahi = 1101
2025-07-02 04:52:32.373 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.373 blo = 214, bhi = 1101
2025-07-02 04:52:32.373
2025-07-02 04:52:32.373 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.373 g = []
2025-07-02 04:52:32.373 if alo < ahi:
2025-07-02 04:52:32.373 if blo < bhi:
2025-07-02 04:52:32.373 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.373 else:
2025-07-02 04:52:32.373 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.373 elif blo < bhi:
2025-07-02 04:52:32.373 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.373
2025-07-02 04:52:32.373 > yield from g
2025-07-02 04:52:32.373
2025-07-02 04:52:32.373 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.373 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.373
2025-07-02 04:52:32.373 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.373 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.373 alo = 214, ahi = 1101
2025-07-02 04:52:32.374 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.374 blo = 214, bhi = 1101
2025-07-02 04:52:32.374
2025-07-02 04:52:32.374 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.374 r"""
2025-07-02 04:52:32.374 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.374 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.374 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.374 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.374
2025-07-02 04:52:32.374 Example:
2025-07-02 04:52:32.374
2025-07-02 04:52:32.374 >>> d = Differ()
2025-07-02 04:52:32.374 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.374 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.374 >>> print(''.join(results), end="")
2025-07-02 04:52:32.374 - abcDefghiJkl
2025-07-02 04:52:32.374 + abcdefGhijkl
2025-07-02 04:52:32.374 """
2025-07-02 04:52:32.375
2025-07-02 04:52:32.375 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.375 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.375 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.375 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.375 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.375
2025-07-02 04:52:32.375 # search for the pair that matches best without being identical
2025-07-02 04:52:32.375 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.375 # on junk -- unless we have to)
2025-07-02 04:52:32.375 for j in range(blo, bhi):
2025-07-02 04:52:32.375 bj = b[j]
2025-07-02 04:52:32.375 cruncher.set_seq2(bj)
2025-07-02 04:52:32.375 for i in range(alo, ahi):
2025-07-02 04:52:32.375 ai = a[i]
2025-07-02 04:52:32.375 if ai == bj:
2025-07-02 04:52:32.375 if eqi is None:
2025-07-02 04:52:32.375 eqi, eqj = i, j
2025-07-02 04:52:32.375 continue
2025-07-02 04:52:32.376 cruncher.set_seq1(ai)
2025-07-02 04:52:32.376 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.376 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.376 # compares by a factor of 3.
2025-07-02 04:52:32.376 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.376 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.376 # of the computation is cached by cruncher
2025-07-02 04:52:32.376 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.376 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.376 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.376 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.376 if best_ratio < cutoff:
2025-07-02 04:52:32.376 # no non-identical "pretty close" pair
2025-07-02 04:52:32.376 if eqi is None:
2025-07-02 04:52:32.376 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.376 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.376 return
2025-07-02 04:52:32.376 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.376 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.376 else:
2025-07-02 04:52:32.377 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.377 eqi = None
2025-07-02 04:52:32.377
2025-07-02 04:52:32.377 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.377 # identical
2025-07-02 04:52:32.377
2025-07-02 04:52:32.377 # pump out diffs from before the synch point
2025-07-02 04:52:32.377 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.377
2025-07-02 04:52:32.377 # do intraline marking on the synch pair
2025-07-02 04:52:32.377 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.377 if eqi is None:
2025-07-02 04:52:32.377 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.377 atags = btags = ""
2025-07-02 04:52:32.377 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.377 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.377 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.377 if tag == 'replace':
2025-07-02 04:52:32.377 atags += '^' * la
2025-07-02 04:52:32.377 btags += '^' * lb
2025-07-02 04:52:32.377 elif tag == 'delete':
2025-07-02 04:52:32.378 atags += '-' * la
2025-07-02 04:52:32.378 elif tag == 'insert':
2025-07-02 04:52:32.378 btags += '+' * lb
2025-07-02 04:52:32.378 elif tag == 'equal':
2025-07-02 04:52:32.378 atags += ' ' * la
2025-07-02 04:52:32.378 btags += ' ' * lb
2025-07-02 04:52:32.378 else:
2025-07-02 04:52:32.378 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.378 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.378 else:
2025-07-02 04:52:32.378 # the synch pair is identical
2025-07-02 04:52:32.378 yield ' ' + aelt
2025-07-02 04:52:32.378
2025-07-02 04:52:32.378 # pump out diffs from after the synch point
2025-07-02 04:52:32.378 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.378
2025-07-02 04:52:32.378 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.378 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.378
2025-07-02 04:52:32.378 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.378 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.378 alo = 215, ahi = 1101
2025-07-02 04:52:32.379 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.379 blo = 215, bhi = 1101
2025-07-02 04:52:32.379
2025-07-02 04:52:32.379 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.379 g = []
2025-07-02 04:52:32.379 if alo < ahi:
2025-07-02 04:52:32.379 if blo < bhi:
2025-07-02 04:52:32.379 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.379 else:
2025-07-02 04:52:32.379 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.379 elif blo < bhi:
2025-07-02 04:52:32.379 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.379
2025-07-02 04:52:32.379 > yield from g
2025-07-02 04:52:32.379
2025-07-02 04:52:32.379 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.379 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.379
2025-07-02 04:52:32.379 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.379 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.379 alo = 215, ahi = 1101
2025-07-02 04:52:32.380 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.380 blo = 215, bhi = 1101
2025-07-02 04:52:32.380
2025-07-02 04:52:32.380 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.380 r"""
2025-07-02 04:52:32.380 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.380 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.380 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.380 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.380
2025-07-02 04:52:32.380 Example:
2025-07-02 04:52:32.380
2025-07-02 04:52:32.380 >>> d = Differ()
2025-07-02 04:52:32.380 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.380 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.380 >>> print(''.join(results), end="")
2025-07-02 04:52:32.380 - abcDefghiJkl
2025-07-02 04:52:32.380 + abcdefGhijkl
2025-07-02 04:52:32.380 """
2025-07-02 04:52:32.381
2025-07-02 04:52:32.381 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.381 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.381 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.381 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.381 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.381
2025-07-02 04:52:32.381 # search for the pair that matches best without being identical
2025-07-02 04:52:32.381 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.381 # on junk -- unless we have to)
2025-07-02 04:52:32.381 for j in range(blo, bhi):
2025-07-02 04:52:32.381 bj = b[j]
2025-07-02 04:52:32.381 cruncher.set_seq2(bj)
2025-07-02 04:52:32.381 for i in range(alo, ahi):
2025-07-02 04:52:32.381 ai = a[i]
2025-07-02 04:52:32.381 if ai == bj:
2025-07-02 04:52:32.381 if eqi is None:
2025-07-02 04:52:32.381 eqi, eqj = i, j
2025-07-02 04:52:32.381 continue
2025-07-02 04:52:32.381 cruncher.set_seq1(ai)
2025-07-02 04:52:32.381 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.381 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.382 # compares by a factor of 3.
2025-07-02 04:52:32.382 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.382 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.382 # of the computation is cached by cruncher
2025-07-02 04:52:32.382 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.382 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.382 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.382 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.382 if best_ratio < cutoff:
2025-07-02 04:52:32.382 # no non-identical "pretty close" pair
2025-07-02 04:52:32.382 if eqi is None:
2025-07-02 04:52:32.382 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.382 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.382 return
2025-07-02 04:52:32.382 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.382 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.382 else:
2025-07-02 04:52:32.382 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.382 eqi = None
2025-07-02 04:52:32.382
2025-07-02 04:52:32.382 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.383 # identical
2025-07-02 04:52:32.383
2025-07-02 04:52:32.383 # pump out diffs from before the synch point
2025-07-02 04:52:32.383 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.383
2025-07-02 04:52:32.383 # do intraline marking on the synch pair
2025-07-02 04:52:32.383 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.383 if eqi is None:
2025-07-02 04:52:32.383 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.383 atags = btags = ""
2025-07-02 04:52:32.383 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.383 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.383 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.383 if tag == 'replace':
2025-07-02 04:52:32.383 atags += '^' * la
2025-07-02 04:52:32.383 btags += '^' * lb
2025-07-02 04:52:32.383 elif tag == 'delete':
2025-07-02 04:52:32.383 atags += '-' * la
2025-07-02 04:52:32.383 elif tag == 'insert':
2025-07-02 04:52:32.383 btags += '+' * lb
2025-07-02 04:52:32.383 elif tag == 'equal':
2025-07-02 04:52:32.384 atags += ' ' * la
2025-07-02 04:52:32.384 btags += ' ' * lb
2025-07-02 04:52:32.384 else:
2025-07-02 04:52:32.384 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.384 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.384 else:
2025-07-02 04:52:32.384 # the synch pair is identical
2025-07-02 04:52:32.384 yield ' ' + aelt
2025-07-02 04:52:32.384
2025-07-02 04:52:32.384 # pump out diffs from after the synch point
2025-07-02 04:52:32.384 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.384
2025-07-02 04:52:32.384 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.384 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.384
2025-07-02 04:52:32.384 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.384 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.384 alo = 216, ahi = 1101
2025-07-02 04:52:32.384 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.385 blo = 216, bhi = 1101
2025-07-02 04:52:32.385
2025-07-02 04:52:32.385 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.385 g = []
2025-07-02 04:52:32.385 if alo < ahi:
2025-07-02 04:52:32.385 if blo < bhi:
2025-07-02 04:52:32.385 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.385 else:
2025-07-02 04:52:32.385 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.385 elif blo < bhi:
2025-07-02 04:52:32.385 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.385
2025-07-02 04:52:32.385 > yield from g
2025-07-02 04:52:32.385
2025-07-02 04:52:32.385 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.385 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.385
2025-07-02 04:52:32.385 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.385 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.385 alo = 216, ahi = 1101
2025-07-02 04:52:32.385 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.386 blo = 216, bhi = 1101
2025-07-02 04:52:32.386
2025-07-02 04:52:32.386 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.386 r"""
2025-07-02 04:52:32.386 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.386 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.386 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.386 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.386
2025-07-02 04:52:32.386 Example:
2025-07-02 04:52:32.386
2025-07-02 04:52:32.386 >>> d = Differ()
2025-07-02 04:52:32.386 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.386 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.386 >>> print(''.join(results), end="")
2025-07-02 04:52:32.386 - abcDefghiJkl
2025-07-02 04:52:32.386 + abcdefGhijkl
2025-07-02 04:52:32.386 """
2025-07-02 04:52:32.386
2025-07-02 04:52:32.387 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.387 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.387 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.387 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.387 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.387
2025-07-02 04:52:32.387 # search for the pair that matches best without being identical
2025-07-02 04:52:32.387 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.387 # on junk -- unless we have to)
2025-07-02 04:52:32.387 for j in range(blo, bhi):
2025-07-02 04:52:32.387 bj = b[j]
2025-07-02 04:52:32.387 cruncher.set_seq2(bj)
2025-07-02 04:52:32.387 for i in range(alo, ahi):
2025-07-02 04:52:32.387 ai = a[i]
2025-07-02 04:52:32.387 if ai == bj:
2025-07-02 04:52:32.387 if eqi is None:
2025-07-02 04:52:32.387 eqi, eqj = i, j
2025-07-02 04:52:32.387 continue
2025-07-02 04:52:32.387 cruncher.set_seq1(ai)
2025-07-02 04:52:32.387 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.387 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.387 # compares by a factor of 3.
2025-07-02 04:52:32.388 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.388 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.388 # of the computation is cached by cruncher
2025-07-02 04:52:32.388 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.388 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.388 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.388 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.388 if best_ratio < cutoff:
2025-07-02 04:52:32.388 # no non-identical "pretty close" pair
2025-07-02 04:52:32.388 if eqi is None:
2025-07-02 04:52:32.388 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.388 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.388 return
2025-07-02 04:52:32.388 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.388 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.388 else:
2025-07-02 04:52:32.388 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.388 eqi = None
2025-07-02 04:52:32.388
2025-07-02 04:52:32.389 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.389 # identical
2025-07-02 04:52:32.389
2025-07-02 04:52:32.389 # pump out diffs from before the synch point
2025-07-02 04:52:32.389 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.389
2025-07-02 04:52:32.389 # do intraline marking on the synch pair
2025-07-02 04:52:32.389 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.389 if eqi is None:
2025-07-02 04:52:32.389 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.389 atags = btags = ""
2025-07-02 04:52:32.389 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.389 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.389 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.389 if tag == 'replace':
2025-07-02 04:52:32.389 atags += '^' * la
2025-07-02 04:52:32.389 btags += '^' * lb
2025-07-02 04:52:32.389 elif tag == 'delete':
2025-07-02 04:52:32.389 atags += '-' * la
2025-07-02 04:52:32.389 elif tag == 'insert':
2025-07-02 04:52:32.389 btags += '+' * lb
2025-07-02 04:52:32.390 elif tag == 'equal':
2025-07-02 04:52:32.390 atags += ' ' * la
2025-07-02 04:52:32.390 btags += ' ' * lb
2025-07-02 04:52:32.390 else:
2025-07-02 04:52:32.390 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.390 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.390 else:
2025-07-02 04:52:32.390 # the synch pair is identical
2025-07-02 04:52:32.390 yield ' ' + aelt
2025-07-02 04:52:32.390
2025-07-02 04:52:32.390 # pump out diffs from after the synch point
2025-07-02 04:52:32.390 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.390
2025-07-02 04:52:32.390 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.390 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.390
2025-07-02 04:52:32.390 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.390 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.390 alo = 217, ahi = 1101
2025-07-02 04:52:32.390 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.390 blo = 217, bhi = 1101
2025-07-02 04:52:32.391
2025-07-02 04:52:32.391 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.391 g = []
2025-07-02 04:52:32.391 if alo < ahi:
2025-07-02 04:52:32.391 if blo < bhi:
2025-07-02 04:52:32.391 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.391 else:
2025-07-02 04:52:32.391 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.391 elif blo < bhi:
2025-07-02 04:52:32.391 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.391
2025-07-02 04:52:32.391 > yield from g
2025-07-02 04:52:32.391
2025-07-02 04:52:32.391 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.391 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.391
2025-07-02 04:52:32.391 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.391 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.391 alo = 217, ahi = 1101
2025-07-02 04:52:32.391 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.391 blo = 217, bhi = 1101
2025-07-02 04:52:32.392
2025-07-02 04:52:32.392 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.392 r"""
2025-07-02 04:52:32.392 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.392 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.392 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.392 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.392
2025-07-02 04:52:32.392 Example:
2025-07-02 04:52:32.392
2025-07-02 04:52:32.392 >>> d = Differ()
2025-07-02 04:52:32.392 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.392 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.392 >>> print(''.join(results), end="")
2025-07-02 04:52:32.392 - abcDefghiJkl
2025-07-02 04:52:32.392 + abcdefGhijkl
2025-07-02 04:52:32.392 """
2025-07-02 04:52:32.393
2025-07-02 04:52:32.393 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.393 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.393 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.393 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.393 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.393
2025-07-02 04:52:32.393 # search for the pair that matches best without being identical
2025-07-02 04:52:32.393 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.393 # on junk -- unless we have to)
2025-07-02 04:52:32.393 for j in range(blo, bhi):
2025-07-02 04:52:32.393 bj = b[j]
2025-07-02 04:52:32.393 cruncher.set_seq2(bj)
2025-07-02 04:52:32.393 for i in range(alo, ahi):
2025-07-02 04:52:32.393 ai = a[i]
2025-07-02 04:52:32.393 if ai == bj:
2025-07-02 04:52:32.393 if eqi is None:
2025-07-02 04:52:32.393 eqi, eqj = i, j
2025-07-02 04:52:32.393 continue
2025-07-02 04:52:32.393 cruncher.set_seq1(ai)
2025-07-02 04:52:32.394 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.394 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.394 # compares by a factor of 3.
2025-07-02 04:52:32.394 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.394 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.394 # of the computation is cached by cruncher
2025-07-02 04:52:32.394 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.394 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.394 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.394 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.394 if best_ratio < cutoff:
2025-07-02 04:52:32.394 # no non-identical "pretty close" pair
2025-07-02 04:52:32.394 if eqi is None:
2025-07-02 04:52:32.394 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.394 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.394 return
2025-07-02 04:52:32.394 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.394 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.394 else:
2025-07-02 04:52:32.394 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.394 eqi = None
2025-07-02 04:52:32.395
2025-07-02 04:52:32.395 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.395 # identical
2025-07-02 04:52:32.395
2025-07-02 04:52:32.395 # pump out diffs from before the synch point
2025-07-02 04:52:32.395 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.395
2025-07-02 04:52:32.395 # do intraline marking on the synch pair
2025-07-02 04:52:32.395 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.395 if eqi is None:
2025-07-02 04:52:32.395 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.395 atags = btags = ""
2025-07-02 04:52:32.395 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.395 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.395 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.395 if tag == 'replace':
2025-07-02 04:52:32.395 atags += '^' * la
2025-07-02 04:52:32.395 btags += '^' * lb
2025-07-02 04:52:32.395 elif tag == 'delete':
2025-07-02 04:52:32.395 atags += '-' * la
2025-07-02 04:52:32.395 elif tag == 'insert':
2025-07-02 04:52:32.395 btags += '+' * lb
2025-07-02 04:52:32.396 elif tag == 'equal':
2025-07-02 04:52:32.396 atags += ' ' * la
2025-07-02 04:52:32.396 btags += ' ' * lb
2025-07-02 04:52:32.396 else:
2025-07-02 04:52:32.396 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.396 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.396 else:
2025-07-02 04:52:32.396 # the synch pair is identical
2025-07-02 04:52:32.396 yield ' ' + aelt
2025-07-02 04:52:32.396
2025-07-02 04:52:32.396 # pump out diffs from after the synch point
2025-07-02 04:52:32.396 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.396
2025-07-02 04:52:32.396 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.396 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.396
2025-07-02 04:52:32.396 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.396 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.396 alo = 218, ahi = 1101
2025-07-02 04:52:32.396 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.396 blo = 218, bhi = 1101
2025-07-02 04:52:32.397
2025-07-02 04:52:32.397 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.397 g = []
2025-07-02 04:52:32.397 if alo < ahi:
2025-07-02 04:52:32.397 if blo < bhi:
2025-07-02 04:52:32.397 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.397 else:
2025-07-02 04:52:32.397 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.397 elif blo < bhi:
2025-07-02 04:52:32.397 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.397
2025-07-02 04:52:32.397 > yield from g
2025-07-02 04:52:32.397
2025-07-02 04:52:32.397 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.397 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.397
2025-07-02 04:52:32.397 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.397 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.397 alo = 218, ahi = 1101
2025-07-02 04:52:32.397 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.397 blo = 218, bhi = 1101
2025-07-02 04:52:32.398
2025-07-02 04:52:32.398 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.398 r"""
2025-07-02 04:52:32.398 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.398 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.398 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.398 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.398
2025-07-02 04:52:32.398 Example:
2025-07-02 04:52:32.398
2025-07-02 04:52:32.398 >>> d = Differ()
2025-07-02 04:52:32.398 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.398 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.398 >>> print(''.join(results), end="")
2025-07-02 04:52:32.398 - abcDefghiJkl
2025-07-02 04:52:32.398 + abcdefGhijkl
2025-07-02 04:52:32.398 """
2025-07-02 04:52:32.399
2025-07-02 04:52:32.399 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.399 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.399 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.399 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.399 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.399
2025-07-02 04:52:32.399 # search for the pair that matches best without being identical
2025-07-02 04:52:32.399 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.399 # on junk -- unless we have to)
2025-07-02 04:52:32.399 for j in range(blo, bhi):
2025-07-02 04:52:32.399 bj = b[j]
2025-07-02 04:52:32.399 cruncher.set_seq2(bj)
2025-07-02 04:52:32.399 for i in range(alo, ahi):
2025-07-02 04:52:32.399 ai = a[i]
2025-07-02 04:52:32.399 if ai == bj:
2025-07-02 04:52:32.399 if eqi is None:
2025-07-02 04:52:32.399 eqi, eqj = i, j
2025-07-02 04:52:32.399 continue
2025-07-02 04:52:32.399 cruncher.set_seq1(ai)
2025-07-02 04:52:32.399 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.400 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.400 # compares by a factor of 3.
2025-07-02 04:52:32.400 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.400 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.400 # of the computation is cached by cruncher
2025-07-02 04:52:32.400 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.400 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.400 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.400 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.400 if best_ratio < cutoff:
2025-07-02 04:52:32.400 # no non-identical "pretty close" pair
2025-07-02 04:52:32.400 if eqi is None:
2025-07-02 04:52:32.400 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.400 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.400 return
2025-07-02 04:52:32.400 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.400 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.400 else:
2025-07-02 04:52:32.400 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.401 eqi = None
2025-07-02 04:52:32.401
2025-07-02 04:52:32.401 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.401 # identical
2025-07-02 04:52:32.401
2025-07-02 04:52:32.401 # pump out diffs from before the synch point
2025-07-02 04:52:32.401 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.401
2025-07-02 04:52:32.401 # do intraline marking on the synch pair
2025-07-02 04:52:32.401 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.401 if eqi is None:
2025-07-02 04:52:32.401 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.401 atags = btags = ""
2025-07-02 04:52:32.401 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.401 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.401 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.401 if tag == 'replace':
2025-07-02 04:52:32.401 atags += '^' * la
2025-07-02 04:52:32.401 btags += '^' * lb
2025-07-02 04:52:32.401 elif tag == 'delete':
2025-07-02 04:52:32.401 atags += '-' * la
2025-07-02 04:52:32.402 elif tag == 'insert':
2025-07-02 04:52:32.402 btags += '+' * lb
2025-07-02 04:52:32.402 elif tag == 'equal':
2025-07-02 04:52:32.402 atags += ' ' * la
2025-07-02 04:52:32.402 btags += ' ' * lb
2025-07-02 04:52:32.402 else:
2025-07-02 04:52:32.402 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.402 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.402 else:
2025-07-02 04:52:32.402 # the synch pair is identical
2025-07-02 04:52:32.402 yield ' ' + aelt
2025-07-02 04:52:32.402
2025-07-02 04:52:32.402 # pump out diffs from after the synch point
2025-07-02 04:52:32.402 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.402
2025-07-02 04:52:32.402 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.402 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.402
2025-07-02 04:52:32.402 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.402 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.402 alo = 219, ahi = 1101
2025-07-02 04:52:32.403 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.403 blo = 219, bhi = 1101
2025-07-02 04:52:32.403
2025-07-02 04:52:32.403 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.403 g = []
2025-07-02 04:52:32.403 if alo < ahi:
2025-07-02 04:52:32.403 if blo < bhi:
2025-07-02 04:52:32.403 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.403 else:
2025-07-02 04:52:32.403 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.403 elif blo < bhi:
2025-07-02 04:52:32.403 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.403
2025-07-02 04:52:32.403 > yield from g
2025-07-02 04:52:32.403
2025-07-02 04:52:32.403 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.403 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.403
2025-07-02 04:52:32.403 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.403 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.403 alo = 219, ahi = 1101
2025-07-02 04:52:32.404 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.404 blo = 219, bhi = 1101
2025-07-02 04:52:32.404
2025-07-02 04:52:32.404 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.404 r"""
2025-07-02 04:52:32.404 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.404 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.404 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.404 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.404
2025-07-02 04:52:32.404 Example:
2025-07-02 04:52:32.404
2025-07-02 04:52:32.404 >>> d = Differ()
2025-07-02 04:52:32.404 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.404 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.404 >>> print(''.join(results), end="")
2025-07-02 04:52:32.404 - abcDefghiJkl
2025-07-02 04:52:32.405 + abcdefGhijkl
2025-07-02 04:52:32.405 """
2025-07-02 04:52:32.405
2025-07-02 04:52:32.405 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.405 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.405 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.405 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.405 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.405
2025-07-02 04:52:32.405 # search for the pair that matches best without being identical
2025-07-02 04:52:32.405 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.405 # on junk -- unless we have to)
2025-07-02 04:52:32.405 for j in range(blo, bhi):
2025-07-02 04:52:32.405 bj = b[j]
2025-07-02 04:52:32.405 cruncher.set_seq2(bj)
2025-07-02 04:52:32.405 for i in range(alo, ahi):
2025-07-02 04:52:32.405 ai = a[i]
2025-07-02 04:52:32.405 if ai == bj:
2025-07-02 04:52:32.405 if eqi is None:
2025-07-02 04:52:32.406 eqi, eqj = i, j
2025-07-02 04:52:32.406 continue
2025-07-02 04:52:32.406 cruncher.set_seq1(ai)
2025-07-02 04:52:32.406 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.406 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.406 # compares by a factor of 3.
2025-07-02 04:52:32.406 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.406 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.406 # of the computation is cached by cruncher
2025-07-02 04:52:32.406 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.406 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.406 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.406 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.406 if best_ratio < cutoff:
2025-07-02 04:52:32.406 # no non-identical "pretty close" pair
2025-07-02 04:52:32.406 if eqi is None:
2025-07-02 04:52:32.406 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.406 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.406 return
2025-07-02 04:52:32.406 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.406 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.406 else:
2025-07-02 04:52:32.407 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.407 eqi = None
2025-07-02 04:52:32.407
2025-07-02 04:52:32.407 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.407 # identical
2025-07-02 04:52:32.407
2025-07-02 04:52:32.407 # pump out diffs from before the synch point
2025-07-02 04:52:32.407 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.407
2025-07-02 04:52:32.407 # do intraline marking on the synch pair
2025-07-02 04:52:32.407 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.407 if eqi is None:
2025-07-02 04:52:32.407 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.407 atags = btags = ""
2025-07-02 04:52:32.407 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.407 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.407 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.407 if tag == 'replace':
2025-07-02 04:52:32.407 atags += '^' * la
2025-07-02 04:52:32.407 btags += '^' * lb
2025-07-02 04:52:32.407 elif tag == 'delete':
2025-07-02 04:52:32.408 atags += '-' * la
2025-07-02 04:52:32.408 elif tag == 'insert':
2025-07-02 04:52:32.408 btags += '+' * lb
2025-07-02 04:52:32.408 elif tag == 'equal':
2025-07-02 04:52:32.408 atags += ' ' * la
2025-07-02 04:52:32.408 btags += ' ' * lb
2025-07-02 04:52:32.408 else:
2025-07-02 04:52:32.408 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.408 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.408 else:
2025-07-02 04:52:32.408 # the synch pair is identical
2025-07-02 04:52:32.408 yield ' ' + aelt
2025-07-02 04:52:32.408
2025-07-02 04:52:32.408 # pump out diffs from after the synch point
2025-07-02 04:52:32.408 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.408
2025-07-02 04:52:32.408 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.408 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.408
2025-07-02 04:52:32.408 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.408 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.409 alo = 220, ahi = 1101
2025-07-02 04:52:32.409 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.409 blo = 220, bhi = 1101
2025-07-02 04:52:32.409
2025-07-02 04:52:32.409 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.409 g = []
2025-07-02 04:52:32.409 if alo < ahi:
2025-07-02 04:52:32.409 if blo < bhi:
2025-07-02 04:52:32.409 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.409 else:
2025-07-02 04:52:32.409 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.409 elif blo < bhi:
2025-07-02 04:52:32.409 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.409
2025-07-02 04:52:32.409 > yield from g
2025-07-02 04:52:32.409
2025-07-02 04:52:32.409 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.409 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.409
2025-07-02 04:52:32.410 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.410 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.410 alo = 220, ahi = 1101
2025-07-02 04:52:32.410 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.410 blo = 220, bhi = 1101
2025-07-02 04:52:32.410
2025-07-02 04:52:32.410 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.410 r"""
2025-07-02 04:52:32.410 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.410 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.410 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.410 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.410
2025-07-02 04:52:32.410 Example:
2025-07-02 04:52:32.410
2025-07-02 04:52:32.410 >>> d = Differ()
2025-07-02 04:52:32.410 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.410 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.410 >>> print(''.join(results), end="")
2025-07-02 04:52:32.410 - abcDefghiJkl
2025-07-02 04:52:32.411 + abcdefGhijkl
2025-07-02 04:52:32.411 """
2025-07-02 04:52:32.411
2025-07-02 04:52:32.411 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.411 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.411 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.411 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.411 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.411
2025-07-02 04:52:32.411 # search for the pair that matches best without being identical
2025-07-02 04:52:32.411 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.411 # on junk -- unless we have to)
2025-07-02 04:52:32.411 for j in range(blo, bhi):
2025-07-02 04:52:32.411 bj = b[j]
2025-07-02 04:52:32.411 cruncher.set_seq2(bj)
2025-07-02 04:52:32.411 for i in range(alo, ahi):
2025-07-02 04:52:32.411 ai = a[i]
2025-07-02 04:52:32.411 if ai == bj:
2025-07-02 04:52:32.412 if eqi is None:
2025-07-02 04:52:32.412 eqi, eqj = i, j
2025-07-02 04:52:32.412 continue
2025-07-02 04:52:32.412 cruncher.set_seq1(ai)
2025-07-02 04:52:32.412 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.412 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.412 # compares by a factor of 3.
2025-07-02 04:52:32.412 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.412 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.412 # of the computation is cached by cruncher
2025-07-02 04:52:32.412 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.412 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.412 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.412 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.412 if best_ratio < cutoff:
2025-07-02 04:52:32.412 # no non-identical "pretty close" pair
2025-07-02 04:52:32.412 if eqi is None:
2025-07-02 04:52:32.412 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.412 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.412 return
2025-07-02 04:52:32.412 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.413 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.413 else:
2025-07-02 04:52:32.413 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.413 eqi = None
2025-07-02 04:52:32.413
2025-07-02 04:52:32.413 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.413 # identical
2025-07-02 04:52:32.413
2025-07-02 04:52:32.413 # pump out diffs from before the synch point
2025-07-02 04:52:32.413 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.413
2025-07-02 04:52:32.413 # do intraline marking on the synch pair
2025-07-02 04:52:32.413 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.413 if eqi is None:
2025-07-02 04:52:32.413 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.413 atags = btags = ""
2025-07-02 04:52:32.413 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.413 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.413 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.413 if tag == 'replace':
2025-07-02 04:52:32.413 atags += '^' * la
2025-07-02 04:52:32.414 btags += '^' * lb
2025-07-02 04:52:32.414 elif tag == 'delete':
2025-07-02 04:52:32.414 atags += '-' * la
2025-07-02 04:52:32.414 elif tag == 'insert':
2025-07-02 04:52:32.414 btags += '+' * lb
2025-07-02 04:52:32.414 elif tag == 'equal':
2025-07-02 04:52:32.414 atags += ' ' * la
2025-07-02 04:52:32.414 btags += ' ' * lb
2025-07-02 04:52:32.414 else:
2025-07-02 04:52:32.414 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.414 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.414 else:
2025-07-02 04:52:32.414 # the synch pair is identical
2025-07-02 04:52:32.414 yield ' ' + aelt
2025-07-02 04:52:32.414
2025-07-02 04:52:32.414 # pump out diffs from after the synch point
2025-07-02 04:52:32.414 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.414
2025-07-02 04:52:32.414 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.414 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.414
2025-07-02 04:52:32.414 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.415 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.415 alo = 221, ahi = 1101
2025-07-02 04:52:32.415 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.415 blo = 221, bhi = 1101
2025-07-02 04:52:32.415
2025-07-02 04:52:32.415 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.415 g = []
2025-07-02 04:52:32.415 if alo < ahi:
2025-07-02 04:52:32.415 if blo < bhi:
2025-07-02 04:52:32.415 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.415 else:
2025-07-02 04:52:32.415 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.415 elif blo < bhi:
2025-07-02 04:52:32.415 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.415
2025-07-02 04:52:32.415 > yield from g
2025-07-02 04:52:32.415
2025-07-02 04:52:32.415 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.415 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.415
2025-07-02 04:52:32.415 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.416 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.416 alo = 221, ahi = 1101
2025-07-02 04:52:32.416 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.416 blo = 221, bhi = 1101
2025-07-02 04:52:32.416
2025-07-02 04:52:32.416 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.416 r"""
2025-07-02 04:52:32.416 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.416 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.416 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.416 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.416
2025-07-02 04:52:32.416 Example:
2025-07-02 04:52:32.416
2025-07-02 04:52:32.416 >>> d = Differ()
2025-07-02 04:52:32.416 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.416 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.416 >>> print(''.join(results), end="")
2025-07-02 04:52:32.416 - abcDefghiJkl
2025-07-02 04:52:32.416 + abcdefGhijkl
2025-07-02 04:52:32.417 """
2025-07-02 04:52:32.417
2025-07-02 04:52:32.417 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.417 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.417 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.417 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.417 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.417
2025-07-02 04:52:32.417 # search for the pair that matches best without being identical
2025-07-02 04:52:32.417 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.417 # on junk -- unless we have to)
2025-07-02 04:52:32.417 for j in range(blo, bhi):
2025-07-02 04:52:32.417 bj = b[j]
2025-07-02 04:52:32.417 cruncher.set_seq2(bj)
2025-07-02 04:52:32.417 for i in range(alo, ahi):
2025-07-02 04:52:32.417 ai = a[i]
2025-07-02 04:52:32.417 if ai == bj:
2025-07-02 04:52:32.417 if eqi is None:
2025-07-02 04:52:32.417 eqi, eqj = i, j
2025-07-02 04:52:32.418 continue
2025-07-02 04:52:32.418 cruncher.set_seq1(ai)
2025-07-02 04:52:32.418 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.418 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.418 # compares by a factor of 3.
2025-07-02 04:52:32.418 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.418 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.418 # of the computation is cached by cruncher
2025-07-02 04:52:32.418 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.418 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.418 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.418 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.418 if best_ratio < cutoff:
2025-07-02 04:52:32.418 # no non-identical "pretty close" pair
2025-07-02 04:52:32.418 if eqi is None:
2025-07-02 04:52:32.418 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.418 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.418 return
2025-07-02 04:52:32.418 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.418 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.418 else:
2025-07-02 04:52:32.419 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.419 eqi = None
2025-07-02 04:52:32.419
2025-07-02 04:52:32.419 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.419 # identical
2025-07-02 04:52:32.419
2025-07-02 04:52:32.419 # pump out diffs from before the synch point
2025-07-02 04:52:32.419 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.419
2025-07-02 04:52:32.419 # do intraline marking on the synch pair
2025-07-02 04:52:32.419 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.419 if eqi is None:
2025-07-02 04:52:32.419 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.419 atags = btags = ""
2025-07-02 04:52:32.419 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.419 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.419 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.419 if tag == 'replace':
2025-07-02 04:52:32.419 atags += '^' * la
2025-07-02 04:52:32.419 btags += '^' * lb
2025-07-02 04:52:32.419 elif tag == 'delete':
2025-07-02 04:52:32.420 atags += '-' * la
2025-07-02 04:52:32.420 elif tag == 'insert':
2025-07-02 04:52:32.420 btags += '+' * lb
2025-07-02 04:52:32.420 elif tag == 'equal':
2025-07-02 04:52:32.420 atags += ' ' * la
2025-07-02 04:52:32.420 btags += ' ' * lb
2025-07-02 04:52:32.420 else:
2025-07-02 04:52:32.420 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.420 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.420 else:
2025-07-02 04:52:32.420 # the synch pair is identical
2025-07-02 04:52:32.420 yield ' ' + aelt
2025-07-02 04:52:32.420
2025-07-02 04:52:32.420 # pump out diffs from after the synch point
2025-07-02 04:52:32.420 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.420
2025-07-02 04:52:32.420 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.420 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.420
2025-07-02 04:52:32.420 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.420 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.421 alo = 224, ahi = 1101
2025-07-02 04:52:32.421 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.421 blo = 224, bhi = 1101
2025-07-02 04:52:32.421
2025-07-02 04:52:32.421 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.421 g = []
2025-07-02 04:52:32.421 if alo < ahi:
2025-07-02 04:52:32.421 if blo < bhi:
2025-07-02 04:52:32.421 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.421 else:
2025-07-02 04:52:32.421 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.421 elif blo < bhi:
2025-07-02 04:52:32.421 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.421
2025-07-02 04:52:32.421 > yield from g
2025-07-02 04:52:32.421
2025-07-02 04:52:32.421 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.421 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.421
2025-07-02 04:52:32.421 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.421 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.422 alo = 224, ahi = 1101
2025-07-02 04:52:32.422 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.422 blo = 224, bhi = 1101
2025-07-02 04:52:32.422
2025-07-02 04:52:32.422 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.422 r"""
2025-07-02 04:52:32.422 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.422 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.422 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.422 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.422
2025-07-02 04:52:32.422 Example:
2025-07-02 04:52:32.422
2025-07-02 04:52:32.422 >>> d = Differ()
2025-07-02 04:52:32.422 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.422 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.422 >>> print(''.join(results), end="")
2025-07-02 04:52:32.422 - abcDefghiJkl
2025-07-02 04:52:32.423 + abcdefGhijkl
2025-07-02 04:52:32.423 """
2025-07-02 04:52:32.423
2025-07-02 04:52:32.423 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.423 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.423 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.423 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.423 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.423
2025-07-02 04:52:32.423 # search for the pair that matches best without being identical
2025-07-02 04:52:32.423 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.423 # on junk -- unless we have to)
2025-07-02 04:52:32.423 for j in range(blo, bhi):
2025-07-02 04:52:32.423 bj = b[j]
2025-07-02 04:52:32.423 cruncher.set_seq2(bj)
2025-07-02 04:52:32.423 for i in range(alo, ahi):
2025-07-02 04:52:32.423 ai = a[i]
2025-07-02 04:52:32.423 if ai == bj:
2025-07-02 04:52:32.423 if eqi is None:
2025-07-02 04:52:32.423 eqi, eqj = i, j
2025-07-02 04:52:32.424 continue
2025-07-02 04:52:32.424 cruncher.set_seq1(ai)
2025-07-02 04:52:32.424 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.424 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.424 # compares by a factor of 3.
2025-07-02 04:52:32.424 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.424 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.424 # of the computation is cached by cruncher
2025-07-02 04:52:32.424 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.424 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.424 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.424 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.424 if best_ratio < cutoff:
2025-07-02 04:52:32.424 # no non-identical "pretty close" pair
2025-07-02 04:52:32.424 if eqi is None:
2025-07-02 04:52:32.424 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.424 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.424 return
2025-07-02 04:52:32.424 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.424 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.425 else:
2025-07-02 04:52:32.425 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.425 eqi = None
2025-07-02 04:52:32.425
2025-07-02 04:52:32.425 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.425 # identical
2025-07-02 04:52:32.425
2025-07-02 04:52:32.425 # pump out diffs from before the synch point
2025-07-02 04:52:32.425 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.425
2025-07-02 04:52:32.425 # do intraline marking on the synch pair
2025-07-02 04:52:32.425 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.425 if eqi is None:
2025-07-02 04:52:32.425 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.425 atags = btags = ""
2025-07-02 04:52:32.425 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.425 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.425 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.425 if tag == 'replace':
2025-07-02 04:52:32.426 atags += '^' * la
2025-07-02 04:52:32.426 btags += '^' * lb
2025-07-02 04:52:32.426 elif tag == 'delete':
2025-07-02 04:52:32.426 atags += '-' * la
2025-07-02 04:52:32.426 elif tag == 'insert':
2025-07-02 04:52:32.426 btags += '+' * lb
2025-07-02 04:52:32.426 elif tag == 'equal':
2025-07-02 04:52:32.426 atags += ' ' * la
2025-07-02 04:52:32.426 btags += ' ' * lb
2025-07-02 04:52:32.426 else:
2025-07-02 04:52:32.426 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.426 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.426 else:
2025-07-02 04:52:32.426 # the synch pair is identical
2025-07-02 04:52:32.426 yield ' ' + aelt
2025-07-02 04:52:32.426
2025-07-02 04:52:32.426 # pump out diffs from after the synch point
2025-07-02 04:52:32.426 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.426
2025-07-02 04:52:32.426 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.427 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.427
2025-07-02 04:52:32.427 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.427 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.427 alo = 225, ahi = 1101
2025-07-02 04:52:32.427 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.427 blo = 225, bhi = 1101
2025-07-02 04:52:32.427
2025-07-02 04:52:32.427 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.427 g = []
2025-07-02 04:52:32.427 if alo < ahi:
2025-07-02 04:52:32.427 if blo < bhi:
2025-07-02 04:52:32.427 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.427 else:
2025-07-02 04:52:32.427 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.427 elif blo < bhi:
2025-07-02 04:52:32.427 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.427
2025-07-02 04:52:32.427 > yield from g
2025-07-02 04:52:32.427
2025-07-02 04:52:32.427 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.428 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.428
2025-07-02 04:52:32.428 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.428 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.428 alo = 225, ahi = 1101
2025-07-02 04:52:32.428 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.428 blo = 225, bhi = 1101
2025-07-02 04:52:32.428
2025-07-02 04:52:32.428 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.428 r"""
2025-07-02 04:52:32.428 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.428 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.428 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.428 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.428
2025-07-02 04:52:32.428 Example:
2025-07-02 04:52:32.428
2025-07-02 04:52:32.428 >>> d = Differ()
2025-07-02 04:52:32.428 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.428 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.429 >>> print(''.join(results), end="")
2025-07-02 04:52:32.429 - abcDefghiJkl
2025-07-02 04:52:32.429 + abcdefGhijkl
2025-07-02 04:52:32.429 """
2025-07-02 04:52:32.429
2025-07-02 04:52:32.429 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.429 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.429 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.429 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.429 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.429
2025-07-02 04:52:32.429 # search for the pair that matches best without being identical
2025-07-02 04:52:32.429 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.429 # on junk -- unless we have to)
2025-07-02 04:52:32.429 for j in range(blo, bhi):
2025-07-02 04:52:32.429 bj = b[j]
2025-07-02 04:52:32.429 cruncher.set_seq2(bj)
2025-07-02 04:52:32.429 for i in range(alo, ahi):
2025-07-02 04:52:32.429 ai = a[i]
2025-07-02 04:52:32.430 if ai == bj:
2025-07-02 04:52:32.430 if eqi is None:
2025-07-02 04:52:32.430 eqi, eqj = i, j
2025-07-02 04:52:32.430 continue
2025-07-02 04:52:32.430 cruncher.set_seq1(ai)
2025-07-02 04:52:32.430 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.430 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.430 # compares by a factor of 3.
2025-07-02 04:52:32.430 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.430 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.430 # of the computation is cached by cruncher
2025-07-02 04:52:32.430 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.430 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.430 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.430 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.430 if best_ratio < cutoff:
2025-07-02 04:52:32.430 # no non-identical "pretty close" pair
2025-07-02 04:52:32.430 if eqi is None:
2025-07-02 04:52:32.430 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.430 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.431 return
2025-07-02 04:52:32.431 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.431 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.431 else:
2025-07-02 04:52:32.431 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.431 eqi = None
2025-07-02 04:52:32.431
2025-07-02 04:52:32.431 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.431 # identical
2025-07-02 04:52:32.431
2025-07-02 04:52:32.431 # pump out diffs from before the synch point
2025-07-02 04:52:32.431 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.431
2025-07-02 04:52:32.431 # do intraline marking on the synch pair
2025-07-02 04:52:32.431 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.431 if eqi is None:
2025-07-02 04:52:32.431 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.431 atags = btags = ""
2025-07-02 04:52:32.431 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.431 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.431 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.432 if tag == 'replace':
2025-07-02 04:52:32.432 atags += '^' * la
2025-07-02 04:52:32.432 btags += '^' * lb
2025-07-02 04:52:32.432 elif tag == 'delete':
2025-07-02 04:52:32.432 atags += '-' * la
2025-07-02 04:52:32.432 elif tag == 'insert':
2025-07-02 04:52:32.432 btags += '+' * lb
2025-07-02 04:52:32.432 elif tag == 'equal':
2025-07-02 04:52:32.432 atags += ' ' * la
2025-07-02 04:52:32.432 btags += ' ' * lb
2025-07-02 04:52:32.432 else:
2025-07-02 04:52:32.432 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.432 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.432 else:
2025-07-02 04:52:32.432 # the synch pair is identical
2025-07-02 04:52:32.432 yield ' ' + aelt
2025-07-02 04:52:32.432
2025-07-02 04:52:32.432 # pump out diffs from after the synch point
2025-07-02 04:52:32.432 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.432
2025-07-02 04:52:32.433 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.433 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.433
2025-07-02 04:52:32.433 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.433 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.433 alo = 226, ahi = 1101
2025-07-02 04:52:32.433 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.433 blo = 226, bhi = 1101
2025-07-02 04:52:32.433
2025-07-02 04:52:32.433 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.433 g = []
2025-07-02 04:52:32.433 if alo < ahi:
2025-07-02 04:52:32.433 if blo < bhi:
2025-07-02 04:52:32.433 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.433 else:
2025-07-02 04:52:32.433 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.433 elif blo < bhi:
2025-07-02 04:52:32.433 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.433
2025-07-02 04:52:32.433 > yield from g
2025-07-02 04:52:32.433
2025-07-02 04:52:32.434 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.434 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.434
2025-07-02 04:52:32.434 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.434 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.434 alo = 226, ahi = 1101
2025-07-02 04:52:32.434 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.434 blo = 226, bhi = 1101
2025-07-02 04:52:32.434
2025-07-02 04:52:32.434 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.434 r"""
2025-07-02 04:52:32.434 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.434 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.434 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.434 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.434
2025-07-02 04:52:32.434 Example:
2025-07-02 04:52:32.434
2025-07-02 04:52:32.434 >>> d = Differ()
2025-07-02 04:52:32.435 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.435 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.435 >>> print(''.join(results), end="")
2025-07-02 04:52:32.435 - abcDefghiJkl
2025-07-02 04:52:32.435 + abcdefGhijkl
2025-07-02 04:52:32.435 """
2025-07-02 04:52:32.435
2025-07-02 04:52:32.435 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.435 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.435 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.435 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.435 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.435
2025-07-02 04:52:32.435 # search for the pair that matches best without being identical
2025-07-02 04:52:32.435 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.435 # on junk -- unless we have to)
2025-07-02 04:52:32.436 for j in range(blo, bhi):
2025-07-02 04:52:32.436 bj = b[j]
2025-07-02 04:52:32.436 cruncher.set_seq2(bj)
2025-07-02 04:52:32.436 for i in range(alo, ahi):
2025-07-02 04:52:32.436 ai = a[i]
2025-07-02 04:52:32.436 if ai == bj:
2025-07-02 04:52:32.436 if eqi is None:
2025-07-02 04:52:32.436 eqi, eqj = i, j
2025-07-02 04:52:32.436 continue
2025-07-02 04:52:32.436 cruncher.set_seq1(ai)
2025-07-02 04:52:32.436 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.436 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.436 # compares by a factor of 3.
2025-07-02 04:52:32.436 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.436 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.436 # of the computation is cached by cruncher
2025-07-02 04:52:32.436 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.436 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.436 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.436 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.436 if best_ratio < cutoff:
2025-07-02 04:52:32.437 # no non-identical "pretty close" pair
2025-07-02 04:52:32.437 if eqi is None:
2025-07-02 04:52:32.437 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.437 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.437 return
2025-07-02 04:52:32.437 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.437 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.437 else:
2025-07-02 04:52:32.437 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.437 eqi = None
2025-07-02 04:52:32.437
2025-07-02 04:52:32.437 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.437 # identical
2025-07-02 04:52:32.437
2025-07-02 04:52:32.437 # pump out diffs from before the synch point
2025-07-02 04:52:32.437 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.437
2025-07-02 04:52:32.437 # do intraline marking on the synch pair
2025-07-02 04:52:32.438 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.438 if eqi is None:
2025-07-02 04:52:32.438 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.438 atags = btags = ""
2025-07-02 04:52:32.438 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.438 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.438 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.438 if tag == 'replace':
2025-07-02 04:52:32.438 atags += '^' * la
2025-07-02 04:52:32.438 btags += '^' * lb
2025-07-02 04:52:32.438 elif tag == 'delete':
2025-07-02 04:52:32.438 atags += '-' * la
2025-07-02 04:52:32.438 elif tag == 'insert':
2025-07-02 04:52:32.438 btags += '+' * lb
2025-07-02 04:52:32.438 elif tag == 'equal':
2025-07-02 04:52:32.438 atags += ' ' * la
2025-07-02 04:52:32.438 btags += ' ' * lb
2025-07-02 04:52:32.438 else:
2025-07-02 04:52:32.438 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.439 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.439 else:
2025-07-02 04:52:32.439 # the synch pair is identical
2025-07-02 04:52:32.439 yield ' ' + aelt
2025-07-02 04:52:32.439
2025-07-02 04:52:32.439 # pump out diffs from after the synch point
2025-07-02 04:52:32.439 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.439
2025-07-02 04:52:32.439 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.439 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.439
2025-07-02 04:52:32.439 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.439 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.439 alo = 227, ahi = 1101
2025-07-02 04:52:32.439 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.440 blo = 227, bhi = 1101
2025-07-02 04:52:32.440
2025-07-02 04:52:32.440 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.440 g = []
2025-07-02 04:52:32.440 if alo < ahi:
2025-07-02 04:52:32.440 if blo < bhi:
2025-07-02 04:52:32.440 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.440 else:
2025-07-02 04:52:32.440 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.440 elif blo < bhi:
2025-07-02 04:52:32.440 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.440
2025-07-02 04:52:32.440 > yield from g
2025-07-02 04:52:32.440
2025-07-02 04:52:32.440 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.440 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.440
2025-07-02 04:52:32.440 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.441 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.441 alo = 227, ahi = 1101
2025-07-02 04:52:32.441 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.441 blo = 227, bhi = 1101
2025-07-02 04:52:32.441
2025-07-02 04:52:32.441 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.441 r"""
2025-07-02 04:52:32.441 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.441 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.441 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.441 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.441
2025-07-02 04:52:32.441 Example:
2025-07-02 04:52:32.441
2025-07-02 04:52:32.441 >>> d = Differ()
2025-07-02 04:52:32.441 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.441 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.442 >>> print(''.join(results), end="")
2025-07-02 04:52:32.442 - abcDefghiJkl
2025-07-02 04:52:32.442 + abcdefGhijkl
2025-07-02 04:52:32.442 """
2025-07-02 04:52:32.442
2025-07-02 04:52:32.442 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.442 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.442 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.442 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.442 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.442
2025-07-02 04:52:32.442 # search for the pair that matches best without being identical
2025-07-02 04:52:32.442 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.442 # on junk -- unless we have to)
2025-07-02 04:52:32.442 for j in range(blo, bhi):
2025-07-02 04:52:32.443 bj = b[j]
2025-07-02 04:52:32.443 cruncher.set_seq2(bj)
2025-07-02 04:52:32.443 for i in range(alo, ahi):
2025-07-02 04:52:32.443 ai = a[i]
2025-07-02 04:52:32.443 if ai == bj:
2025-07-02 04:52:32.443 if eqi is None:
2025-07-02 04:52:32.443 eqi, eqj = i, j
2025-07-02 04:52:32.443 continue
2025-07-02 04:52:32.443 cruncher.set_seq1(ai)
2025-07-02 04:52:32.443 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.443 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.443 # compares by a factor of 3.
2025-07-02 04:52:32.443 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.443 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.443 # of the computation is cached by cruncher
2025-07-02 04:52:32.443 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.444 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.444 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.444 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.444 if best_ratio < cutoff:
2025-07-02 04:52:32.444 # no non-identical "pretty close" pair
2025-07-02 04:52:32.444 if eqi is None:
2025-07-02 04:52:32.444 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.444 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.444 return
2025-07-02 04:52:32.444 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.444 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.444 else:
2025-07-02 04:52:32.444 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.444 eqi = None
2025-07-02 04:52:32.444
2025-07-02 04:52:32.444 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.444 # identical
2025-07-02 04:52:32.444
2025-07-02 04:52:32.445 # pump out diffs from before the synch point
2025-07-02 04:52:32.445 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.445
2025-07-02 04:52:32.445 # do intraline marking on the synch pair
2025-07-02 04:52:32.445 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.445 if eqi is None:
2025-07-02 04:52:32.445 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.445 atags = btags = ""
2025-07-02 04:52:32.445 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.445 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.445 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.445 if tag == 'replace':
2025-07-02 04:52:32.445 atags += '^' * la
2025-07-02 04:52:32.445 btags += '^' * lb
2025-07-02 04:52:32.445 elif tag == 'delete':
2025-07-02 04:52:32.445 atags += '-' * la
2025-07-02 04:52:32.445 elif tag == 'insert':
2025-07-02 04:52:32.445 btags += '+' * lb
2025-07-02 04:52:32.445 elif tag == 'equal':
2025-07-02 04:52:32.445 atags += ' ' * la
2025-07-02 04:52:32.446 btags += ' ' * lb
2025-07-02 04:52:32.446 else:
2025-07-02 04:52:32.446 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.446 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.446 else:
2025-07-02 04:52:32.446 # the synch pair is identical
2025-07-02 04:52:32.446 yield ' ' + aelt
2025-07-02 04:52:32.446
2025-07-02 04:52:32.446 # pump out diffs from after the synch point
2025-07-02 04:52:32.446 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.446
2025-07-02 04:52:32.446 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.446 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.446
2025-07-02 04:52:32.446 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.446 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.446 alo = 228, ahi = 1101
2025-07-02 04:52:32.446 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.446 blo = 228, bhi = 1101
2025-07-02 04:52:32.446
2025-07-02 04:52:32.446 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.446 g = []
2025-07-02 04:52:32.446 if alo < ahi:
2025-07-02 04:52:32.447 if blo < bhi:
2025-07-02 04:52:32.447 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.447 else:
2025-07-02 04:52:32.447 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.447 elif blo < bhi:
2025-07-02 04:52:32.447 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.447
2025-07-02 04:52:32.447 > yield from g
2025-07-02 04:52:32.447
2025-07-02 04:52:32.447 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.447 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.447
2025-07-02 04:52:32.447 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.447 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.447 alo = 228, ahi = 1101
2025-07-02 04:52:32.447 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.447 blo = 228, bhi = 1101
2025-07-02 04:52:32.447
2025-07-02 04:52:32.447 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.448 r"""
2025-07-02 04:52:32.448 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.448 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.448 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.448 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.448
2025-07-02 04:52:32.448 Example:
2025-07-02 04:52:32.448
2025-07-02 04:52:32.448 >>> d = Differ()
2025-07-02 04:52:32.448 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.448 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.448 >>> print(''.join(results), end="")
2025-07-02 04:52:32.448 - abcDefghiJkl
2025-07-02 04:52:32.448 + abcdefGhijkl
2025-07-02 04:52:32.448 """
2025-07-02 04:52:32.448
2025-07-02 04:52:32.448 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.448 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.449 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.449 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.449 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.449
2025-07-02 04:52:32.449 # search for the pair that matches best without being identical
2025-07-02 04:52:32.449 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.449 # on junk -- unless we have to)
2025-07-02 04:52:32.449 for j in range(blo, bhi):
2025-07-02 04:52:32.449 bj = b[j]
2025-07-02 04:52:32.449 cruncher.set_seq2(bj)
2025-07-02 04:52:32.449 for i in range(alo, ahi):
2025-07-02 04:52:32.449 ai = a[i]
2025-07-02 04:52:32.449 if ai == bj:
2025-07-02 04:52:32.449 if eqi is None:
2025-07-02 04:52:32.449 eqi, eqj = i, j
2025-07-02 04:52:32.449 continue
2025-07-02 04:52:32.449 cruncher.set_seq1(ai)
2025-07-02 04:52:32.449 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.449 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.450 # compares by a factor of 3.
2025-07-02 04:52:32.450 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.450 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.450 # of the computation is cached by cruncher
2025-07-02 04:52:32.450 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.450 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.450 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.450 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.450 if best_ratio < cutoff:
2025-07-02 04:52:32.450 # no non-identical "pretty close" pair
2025-07-02 04:52:32.450 if eqi is None:
2025-07-02 04:52:32.450 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.450 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.450 return
2025-07-02 04:52:32.450 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.450 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.450 else:
2025-07-02 04:52:32.450 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.450 eqi = None
2025-07-02 04:52:32.451
2025-07-02 04:52:32.451 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.451 # identical
2025-07-02 04:52:32.451
2025-07-02 04:52:32.451 # pump out diffs from before the synch point
2025-07-02 04:52:32.451 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.451
2025-07-02 04:52:32.451 # do intraline marking on the synch pair
2025-07-02 04:52:32.451 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.451 if eqi is None:
2025-07-02 04:52:32.451 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.451 atags = btags = ""
2025-07-02 04:52:32.451 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.451 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.451 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.451 if tag == 'replace':
2025-07-02 04:52:32.451 atags += '^' * la
2025-07-02 04:52:32.451 btags += '^' * lb
2025-07-02 04:52:32.451 elif tag == 'delete':
2025-07-02 04:52:32.452 atags += '-' * la
2025-07-02 04:52:32.452 elif tag == 'insert':
2025-07-02 04:52:32.452 btags += '+' * lb
2025-07-02 04:52:32.452 elif tag == 'equal':
2025-07-02 04:52:32.452 atags += ' ' * la
2025-07-02 04:52:32.452 btags += ' ' * lb
2025-07-02 04:52:32.452 else:
2025-07-02 04:52:32.452 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.452 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.452 else:
2025-07-02 04:52:32.452 # the synch pair is identical
2025-07-02 04:52:32.452 yield ' ' + aelt
2025-07-02 04:52:32.452
2025-07-02 04:52:32.452 # pump out diffs from after the synch point
2025-07-02 04:52:32.452 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.452
2025-07-02 04:52:32.452 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.452 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.453
2025-07-02 04:52:32.453 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.453 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.453 alo = 229, ahi = 1101
2025-07-02 04:52:32.453 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.453 blo = 229, bhi = 1101
2025-07-02 04:52:32.453
2025-07-02 04:52:32.453 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.453 g = []
2025-07-02 04:52:32.453 if alo < ahi:
2025-07-02 04:52:32.453 if blo < bhi:
2025-07-02 04:52:32.453 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.453 else:
2025-07-02 04:52:32.453 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.453 elif blo < bhi:
2025-07-02 04:52:32.453 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.453
2025-07-02 04:52:32.453 > yield from g
2025-07-02 04:52:32.454
2025-07-02 04:52:32.454 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.454 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.454
2025-07-02 04:52:32.454 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.454 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.454 alo = 229, ahi = 1101
2025-07-02 04:52:32.454 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.454 blo = 229, bhi = 1101
2025-07-02 04:52:32.454
2025-07-02 04:52:32.454 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.454 r"""
2025-07-02 04:52:32.454 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.454 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.454 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.454 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.454
2025-07-02 04:52:32.454 Example:
2025-07-02 04:52:32.455
2025-07-02 04:52:32.455 >>> d = Differ()
2025-07-02 04:52:32.455 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.455 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.455 >>> print(''.join(results), end="")
2025-07-02 04:52:32.455 - abcDefghiJkl
2025-07-02 04:52:32.455 + abcdefGhijkl
2025-07-02 04:52:32.455 """
2025-07-02 04:52:32.455
2025-07-02 04:52:32.455 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.455 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.455 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.455 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.455 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.455
2025-07-02 04:52:32.455 # search for the pair that matches best without being identical
2025-07-02 04:52:32.456 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.456 # on junk -- unless we have to)
2025-07-02 04:52:32.456 for j in range(blo, bhi):
2025-07-02 04:52:32.456 bj = b[j]
2025-07-02 04:52:32.456 cruncher.set_seq2(bj)
2025-07-02 04:52:32.456 for i in range(alo, ahi):
2025-07-02 04:52:32.456 ai = a[i]
2025-07-02 04:52:32.456 if ai == bj:
2025-07-02 04:52:32.456 if eqi is None:
2025-07-02 04:52:32.456 eqi, eqj = i, j
2025-07-02 04:52:32.456 continue
2025-07-02 04:52:32.456 cruncher.set_seq1(ai)
2025-07-02 04:52:32.456 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.456 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.456 # compares by a factor of 3.
2025-07-02 04:52:32.456 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.456 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.456 # of the computation is cached by cruncher
2025-07-02 04:52:32.456 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.457 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.457 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.457 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.457 if best_ratio < cutoff:
2025-07-02 04:52:32.457 # no non-identical "pretty close" pair
2025-07-02 04:52:32.457 if eqi is None:
2025-07-02 04:52:32.457 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.457 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.457 return
2025-07-02 04:52:32.457 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.457 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.457 else:
2025-07-02 04:52:32.457 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.457 eqi = None
2025-07-02 04:52:32.457
2025-07-02 04:52:32.457 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.457 # identical
2025-07-02 04:52:32.457
2025-07-02 04:52:32.457 # pump out diffs from before the synch point
2025-07-02 04:52:32.458 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.458
2025-07-02 04:52:32.458 # do intraline marking on the synch pair
2025-07-02 04:52:32.458 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.458 if eqi is None:
2025-07-02 04:52:32.458 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.458 atags = btags = ""
2025-07-02 04:52:32.458 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.458 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.458 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.458 if tag == 'replace':
2025-07-02 04:52:32.458 atags += '^' * la
2025-07-02 04:52:32.458 btags += '^' * lb
2025-07-02 04:52:32.458 elif tag == 'delete':
2025-07-02 04:52:32.458 atags += '-' * la
2025-07-02 04:52:32.458 elif tag == 'insert':
2025-07-02 04:52:32.458 btags += '+' * lb
2025-07-02 04:52:32.458 elif tag == 'equal':
2025-07-02 04:52:32.458 atags += ' ' * la
2025-07-02 04:52:32.459 btags += ' ' * lb
2025-07-02 04:52:32.459 else:
2025-07-02 04:52:32.459 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.459 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.459 else:
2025-07-02 04:52:32.459 # the synch pair is identical
2025-07-02 04:52:32.459 yield ' ' + aelt
2025-07-02 04:52:32.459
2025-07-02 04:52:32.459 # pump out diffs from after the synch point
2025-07-02 04:52:32.459 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.459
2025-07-02 04:52:32.459 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.459 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.459
2025-07-02 04:52:32.459 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.459 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.459 alo = 230, ahi = 1101
2025-07-02 04:52:32.459 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.459 blo = 230, bhi = 1101
2025-07-02 04:52:32.460
2025-07-02 04:52:32.460 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.460 g = []
2025-07-02 04:52:32.460 if alo < ahi:
2025-07-02 04:52:32.460 if blo < bhi:
2025-07-02 04:52:32.460 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.460 else:
2025-07-02 04:52:32.460 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.460 elif blo < bhi:
2025-07-02 04:52:32.460 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.460
2025-07-02 04:52:32.460 > yield from g
2025-07-02 04:52:32.460
2025-07-02 04:52:32.460 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.460 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.460
2025-07-02 04:52:32.460 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.460 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.460 alo = 230, ahi = 1101
2025-07-02 04:52:32.461 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.461 blo = 230, bhi = 1101
2025-07-02 04:52:32.461
2025-07-02 04:52:32.461 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.461 r"""
2025-07-02 04:52:32.461 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.461 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.461 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.461 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.461
2025-07-02 04:52:32.461 Example:
2025-07-02 04:52:32.461
2025-07-02 04:52:32.461 >>> d = Differ()
2025-07-02 04:52:32.461 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.461 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.461 >>> print(''.join(results), end="")
2025-07-02 04:52:32.461 - abcDefghiJkl
2025-07-02 04:52:32.462 + abcdefGhijkl
2025-07-02 04:52:32.462 """
2025-07-02 04:52:32.462
2025-07-02 04:52:32.462 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.462 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.462 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.462 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.462 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.462
2025-07-02 04:52:32.462 # search for the pair that matches best without being identical
2025-07-02 04:52:32.462 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.462 # on junk -- unless we have to)
2025-07-02 04:52:32.462 for j in range(blo, bhi):
2025-07-02 04:52:32.462 bj = b[j]
2025-07-02 04:52:32.462 cruncher.set_seq2(bj)
2025-07-02 04:52:32.462 for i in range(alo, ahi):
2025-07-02 04:52:32.462 ai = a[i]
2025-07-02 04:52:32.462 if ai == bj:
2025-07-02 04:52:32.463 if eqi is None:
2025-07-02 04:52:32.463 eqi, eqj = i, j
2025-07-02 04:52:32.463 continue
2025-07-02 04:52:32.463 cruncher.set_seq1(ai)
2025-07-02 04:52:32.463 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.463 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.463 # compares by a factor of 3.
2025-07-02 04:52:32.463 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.463 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.463 # of the computation is cached by cruncher
2025-07-02 04:52:32.463 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.463 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.463 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.463 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.463 if best_ratio < cutoff:
2025-07-02 04:52:32.463 # no non-identical "pretty close" pair
2025-07-02 04:52:32.463 if eqi is None:
2025-07-02 04:52:32.463 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.463 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.464 return
2025-07-02 04:52:32.464 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.464 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.464 else:
2025-07-02 04:52:32.464 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.464 eqi = None
2025-07-02 04:52:32.464
2025-07-02 04:52:32.464 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.464 # identical
2025-07-02 04:52:32.464
2025-07-02 04:52:32.464 # pump out diffs from before the synch point
2025-07-02 04:52:32.464 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.464
2025-07-02 04:52:32.464 # do intraline marking on the synch pair
2025-07-02 04:52:32.464 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.464 if eqi is None:
2025-07-02 04:52:32.464 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.464 atags = btags = ""
2025-07-02 04:52:32.464 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.464 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.465 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.465 if tag == 'replace':
2025-07-02 04:52:32.465 atags += '^' * la
2025-07-02 04:52:32.465 btags += '^' * lb
2025-07-02 04:52:32.465 elif tag == 'delete':
2025-07-02 04:52:32.465 atags += '-' * la
2025-07-02 04:52:32.465 elif tag == 'insert':
2025-07-02 04:52:32.465 btags += '+' * lb
2025-07-02 04:52:32.465 elif tag == 'equal':
2025-07-02 04:52:32.465 atags += ' ' * la
2025-07-02 04:52:32.465 btags += ' ' * lb
2025-07-02 04:52:32.465 else:
2025-07-02 04:52:32.465 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.465 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.465 else:
2025-07-02 04:52:32.465 # the synch pair is identical
2025-07-02 04:52:32.465 yield ' ' + aelt
2025-07-02 04:52:32.465
2025-07-02 04:52:32.465 # pump out diffs from after the synch point
2025-07-02 04:52:32.466 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.466
2025-07-02 04:52:32.466 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.466 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.466
2025-07-02 04:52:32.466 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.466 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.466 alo = 231, ahi = 1101
2025-07-02 04:52:32.466 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.466 blo = 231, bhi = 1101
2025-07-02 04:52:32.466
2025-07-02 04:52:32.466 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.466 g = []
2025-07-02 04:52:32.466 if alo < ahi:
2025-07-02 04:52:32.466 if blo < bhi:
2025-07-02 04:52:32.466 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.466 else:
2025-07-02 04:52:32.466 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.466 elif blo < bhi:
2025-07-02 04:52:32.467 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.467
2025-07-02 04:52:32.467 > yield from g
2025-07-02 04:52:32.467
2025-07-02 04:52:32.467 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.467 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.467
2025-07-02 04:52:32.467 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.467 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.467 alo = 231, ahi = 1101
2025-07-02 04:52:32.467 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.467 blo = 231, bhi = 1101
2025-07-02 04:52:32.467
2025-07-02 04:52:32.467 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.467 r"""
2025-07-02 04:52:32.467 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.467 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.467 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.467 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.468
2025-07-02 04:52:32.468 Example:
2025-07-02 04:52:32.468
2025-07-02 04:52:32.468 >>> d = Differ()
2025-07-02 04:52:32.468 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.468 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.468 >>> print(''.join(results), end="")
2025-07-02 04:52:32.468 - abcDefghiJkl
2025-07-02 04:52:32.468 + abcdefGhijkl
2025-07-02 04:52:32.468 """
2025-07-02 04:52:32.468
2025-07-02 04:52:32.468 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.468 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.468 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.468 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.468 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.468
2025-07-02 04:52:32.469 # search for the pair that matches best without being identical
2025-07-02 04:52:32.469 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.469 # on junk -- unless we have to)
2025-07-02 04:52:32.469 for j in range(blo, bhi):
2025-07-02 04:52:32.469 bj = b[j]
2025-07-02 04:52:32.469 cruncher.set_seq2(bj)
2025-07-02 04:52:32.469 for i in range(alo, ahi):
2025-07-02 04:52:32.469 ai = a[i]
2025-07-02 04:52:32.469 if ai == bj:
2025-07-02 04:52:32.469 if eqi is None:
2025-07-02 04:52:32.469 eqi, eqj = i, j
2025-07-02 04:52:32.469 continue
2025-07-02 04:52:32.469 cruncher.set_seq1(ai)
2025-07-02 04:52:32.469 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.469 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.469 # compares by a factor of 3.
2025-07-02 04:52:32.469 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.469 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.469 # of the computation is cached by cruncher
2025-07-02 04:52:32.470 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.470 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.470 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.470 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.470 if best_ratio < cutoff:
2025-07-02 04:52:32.470 # no non-identical "pretty close" pair
2025-07-02 04:52:32.470 if eqi is None:
2025-07-02 04:52:32.470 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.470 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.470 return
2025-07-02 04:52:32.470 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.470 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.470 else:
2025-07-02 04:52:32.470 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.470 eqi = None
2025-07-02 04:52:32.470
2025-07-02 04:52:32.470 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.470 # identical
2025-07-02 04:52:32.471
2025-07-02 04:52:32.471 # pump out diffs from before the synch point
2025-07-02 04:52:32.471 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.471
2025-07-02 04:52:32.471 # do intraline marking on the synch pair
2025-07-02 04:52:32.471 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.471 if eqi is None:
2025-07-02 04:52:32.471 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.471 atags = btags = ""
2025-07-02 04:52:32.471 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.471 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.471 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.471 if tag == 'replace':
2025-07-02 04:52:32.471 atags += '^' * la
2025-07-02 04:52:32.471 btags += '^' * lb
2025-07-02 04:52:32.471 elif tag == 'delete':
2025-07-02 04:52:32.471 atags += '-' * la
2025-07-02 04:52:32.471 elif tag == 'insert':
2025-07-02 04:52:32.472 btags += '+' * lb
2025-07-02 04:52:32.472 elif tag == 'equal':
2025-07-02 04:52:32.472 atags += ' ' * la
2025-07-02 04:52:32.472 btags += ' ' * lb
2025-07-02 04:52:32.472 else:
2025-07-02 04:52:32.472 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.472 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.472 else:
2025-07-02 04:52:32.472 # the synch pair is identical
2025-07-02 04:52:32.472 yield ' ' + aelt
2025-07-02 04:52:32.472
2025-07-02 04:52:32.472 # pump out diffs from after the synch point
2025-07-02 04:52:32.472 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.472
2025-07-02 04:52:32.472 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.472 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.472
2025-07-02 04:52:32.472 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.472 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.473 alo = 232, ahi = 1101
2025-07-02 04:52:32.473 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.473 blo = 232, bhi = 1101
2025-07-02 04:52:32.473
2025-07-02 04:52:32.473 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.473 g = []
2025-07-02 04:52:32.473 if alo < ahi:
2025-07-02 04:52:32.473 if blo < bhi:
2025-07-02 04:52:32.473 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.473 else:
2025-07-02 04:52:32.473 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.473 elif blo < bhi:
2025-07-02 04:52:32.473 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.473
2025-07-02 04:52:32.473 > yield from g
2025-07-02 04:52:32.473
2025-07-02 04:52:32.473 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.473 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.473
2025-07-02 04:52:32.474 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.474 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.474 alo = 232, ahi = 1101
2025-07-02 04:52:32.474 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.474 blo = 232, bhi = 1101
2025-07-02 04:52:32.474
2025-07-02 04:52:32.474 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.474 r"""
2025-07-02 04:52:32.474 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.474 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.474 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.474 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.474
2025-07-02 04:52:32.474 Example:
2025-07-02 04:52:32.474
2025-07-02 04:52:32.474 >>> d = Differ()
2025-07-02 04:52:32.474 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.474 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.475 >>> print(''.join(results), end="")
2025-07-02 04:52:32.475 - abcDefghiJkl
2025-07-02 04:52:32.475 + abcdefGhijkl
2025-07-02 04:52:32.475 """
2025-07-02 04:52:32.475
2025-07-02 04:52:32.475 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.475 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.475 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.475 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.475 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.475
2025-07-02 04:52:32.475 # search for the pair that matches best without being identical
2025-07-02 04:52:32.475 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.475 # on junk -- unless we have to)
2025-07-02 04:52:32.475 for j in range(blo, bhi):
2025-07-02 04:52:32.475 bj = b[j]
2025-07-02 04:52:32.475 cruncher.set_seq2(bj)
2025-07-02 04:52:32.476 for i in range(alo, ahi):
2025-07-02 04:52:32.476 ai = a[i]
2025-07-02 04:52:32.476 if ai == bj:
2025-07-02 04:52:32.476 if eqi is None:
2025-07-02 04:52:32.476 eqi, eqj = i, j
2025-07-02 04:52:32.476 continue
2025-07-02 04:52:32.476 cruncher.set_seq1(ai)
2025-07-02 04:52:32.476 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.476 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.476 # compares by a factor of 3.
2025-07-02 04:52:32.476 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.476 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.476 # of the computation is cached by cruncher
2025-07-02 04:52:32.476 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.476 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.476 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.476 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.476 if best_ratio < cutoff:
2025-07-02 04:52:32.476 # no non-identical "pretty close" pair
2025-07-02 04:52:32.477 if eqi is None:
2025-07-02 04:52:32.477 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.477 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.477 return
2025-07-02 04:52:32.477 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.477 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.477 else:
2025-07-02 04:52:32.477 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.477 eqi = None
2025-07-02 04:52:32.477
2025-07-02 04:52:32.477 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.477 # identical
2025-07-02 04:52:32.477
2025-07-02 04:52:32.477 # pump out diffs from before the synch point
2025-07-02 04:52:32.477 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.477
2025-07-02 04:52:32.477 # do intraline marking on the synch pair
2025-07-02 04:52:32.477 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.477 if eqi is None:
2025-07-02 04:52:32.478 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.478 atags = btags = ""
2025-07-02 04:52:32.478 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.478 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.478 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.478 if tag == 'replace':
2025-07-02 04:52:32.478 atags += '^' * la
2025-07-02 04:52:32.478 btags += '^' * lb
2025-07-02 04:52:32.478 elif tag == 'delete':
2025-07-02 04:52:32.478 atags += '-' * la
2025-07-02 04:52:32.478 elif tag == 'insert':
2025-07-02 04:52:32.478 btags += '+' * lb
2025-07-02 04:52:32.478 elif tag == 'equal':
2025-07-02 04:52:32.478 atags += ' ' * la
2025-07-02 04:52:32.478 btags += ' ' * lb
2025-07-02 04:52:32.478 else:
2025-07-02 04:52:32.478 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.478 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.478 else:
2025-07-02 04:52:32.479 # the synch pair is identical
2025-07-02 04:52:32.479 yield ' ' + aelt
2025-07-02 04:52:32.479
2025-07-02 04:52:32.479 # pump out diffs from after the synch point
2025-07-02 04:52:32.479 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.479
2025-07-02 04:52:32.479 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.479 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.479
2025-07-02 04:52:32.479 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.479 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.479 alo = 233, ahi = 1101
2025-07-02 04:52:32.479 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.479 blo = 233, bhi = 1101
2025-07-02 04:52:32.479
2025-07-02 04:52:32.479 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.479 g = []
2025-07-02 04:52:32.479 if alo < ahi:
2025-07-02 04:52:32.480 if blo < bhi:
2025-07-02 04:52:32.480 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.480 else:
2025-07-02 04:52:32.480 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.480 elif blo < bhi:
2025-07-02 04:52:32.480 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.480
2025-07-02 04:52:32.480 > yield from g
2025-07-02 04:52:32.480
2025-07-02 04:52:32.480 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.480 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.480
2025-07-02 04:52:32.480 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.480 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.480 alo = 233, ahi = 1101
2025-07-02 04:52:32.480 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.480 blo = 233, bhi = 1101
2025-07-02 04:52:32.481
2025-07-02 04:52:32.481 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.481 r"""
2025-07-02 04:52:32.481 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.481 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.481 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.481 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.481
2025-07-02 04:52:32.481 Example:
2025-07-02 04:52:32.481
2025-07-02 04:52:32.481 >>> d = Differ()
2025-07-02 04:52:32.481 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.481 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.481 >>> print(''.join(results), end="")
2025-07-02 04:52:32.481 - abcDefghiJkl
2025-07-02 04:52:32.481 + abcdefGhijkl
2025-07-02 04:52:32.481 """
2025-07-02 04:52:32.482
2025-07-02 04:52:32.482 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.482 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.482 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.482 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.482 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.482
2025-07-02 04:52:32.482 # search for the pair that matches best without being identical
2025-07-02 04:52:32.482 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.482 # on junk -- unless we have to)
2025-07-02 04:52:32.482 for j in range(blo, bhi):
2025-07-02 04:52:32.482 bj = b[j]
2025-07-02 04:52:32.482 cruncher.set_seq2(bj)
2025-07-02 04:52:32.482 for i in range(alo, ahi):
2025-07-02 04:52:32.482 ai = a[i]
2025-07-02 04:52:32.482 if ai == bj:
2025-07-02 04:52:32.482 if eqi is None:
2025-07-02 04:52:32.482 eqi, eqj = i, j
2025-07-02 04:52:32.482 continue
2025-07-02 04:52:32.483 cruncher.set_seq1(ai)
2025-07-02 04:52:32.483 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.483 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.483 # compares by a factor of 3.
2025-07-02 04:52:32.483 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.483 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.483 # of the computation is cached by cruncher
2025-07-02 04:52:32.483 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.483 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.483 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.483 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.483 if best_ratio < cutoff:
2025-07-02 04:52:32.483 # no non-identical "pretty close" pair
2025-07-02 04:52:32.483 if eqi is None:
2025-07-02 04:52:32.483 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.483 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.483 return
2025-07-02 04:52:32.483 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.483 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.484 else:
2025-07-02 04:52:32.484 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.484 eqi = None
2025-07-02 04:52:32.484
2025-07-02 04:52:32.484 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.484 # identical
2025-07-02 04:52:32.484
2025-07-02 04:52:32.484 # pump out diffs from before the synch point
2025-07-02 04:52:32.484 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.484
2025-07-02 04:52:32.484 # do intraline marking on the synch pair
2025-07-02 04:52:32.484 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.484 if eqi is None:
2025-07-02 04:52:32.484 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.484 atags = btags = ""
2025-07-02 04:52:32.484 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.484 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.485 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.485 if tag == 'replace':
2025-07-02 04:52:32.485 atags += '^' * la
2025-07-02 04:52:32.485 btags += '^' * lb
2025-07-02 04:52:32.485 elif tag == 'delete':
2025-07-02 04:52:32.485 atags += '-' * la
2025-07-02 04:52:32.485 elif tag == 'insert':
2025-07-02 04:52:32.485 btags += '+' * lb
2025-07-02 04:52:32.485 elif tag == 'equal':
2025-07-02 04:52:32.485 atags += ' ' * la
2025-07-02 04:52:32.485 btags += ' ' * lb
2025-07-02 04:52:32.485 else:
2025-07-02 04:52:32.485 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.485 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.485 else:
2025-07-02 04:52:32.485 # the synch pair is identical
2025-07-02 04:52:32.485 yield ' ' + aelt
2025-07-02 04:52:32.485
2025-07-02 04:52:32.485 # pump out diffs from after the synch point
2025-07-02 04:52:32.486 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.486
2025-07-02 04:52:32.486 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.486 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.486
2025-07-02 04:52:32.486 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.486 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.486 alo = 234, ahi = 1101
2025-07-02 04:52:32.486 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.486 blo = 234, bhi = 1101
2025-07-02 04:52:32.486
2025-07-02 04:52:32.486 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.486 g = []
2025-07-02 04:52:32.486 if alo < ahi:
2025-07-02 04:52:32.486 if blo < bhi:
2025-07-02 04:52:32.486 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.486 else:
2025-07-02 04:52:32.486 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.487 elif blo < bhi:
2025-07-02 04:52:32.487 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.487
2025-07-02 04:52:32.487 > yield from g
2025-07-02 04:52:32.487
2025-07-02 04:52:32.487 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.487 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.487
2025-07-02 04:52:32.487 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.487 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.487 alo = 234, ahi = 1101
2025-07-02 04:52:32.487 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.487 blo = 234, bhi = 1101
2025-07-02 04:52:32.487
2025-07-02 04:52:32.487 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.487 r"""
2025-07-02 04:52:32.487 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.487 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.487 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.487 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.488
2025-07-02 04:52:32.488 Example:
2025-07-02 04:52:32.488
2025-07-02 04:52:32.488 >>> d = Differ()
2025-07-02 04:52:32.488 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.488 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.488 >>> print(''.join(results), end="")
2025-07-02 04:52:32.488 - abcDefghiJkl
2025-07-02 04:52:32.488 + abcdefGhijkl
2025-07-02 04:52:32.488 """
2025-07-02 04:52:32.488
2025-07-02 04:52:32.488 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.488 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.488 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.488 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.488 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.488
2025-07-02 04:52:32.488 # search for the pair that matches best without being identical
2025-07-02 04:52:32.488 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.489 # on junk -- unless we have to)
2025-07-02 04:52:32.489 for j in range(blo, bhi):
2025-07-02 04:52:32.489 bj = b[j]
2025-07-02 04:52:32.489 cruncher.set_seq2(bj)
2025-07-02 04:52:32.489 for i in range(alo, ahi):
2025-07-02 04:52:32.489 ai = a[i]
2025-07-02 04:52:32.489 if ai == bj:
2025-07-02 04:52:32.489 if eqi is None:
2025-07-02 04:52:32.489 eqi, eqj = i, j
2025-07-02 04:52:32.489 continue
2025-07-02 04:52:32.489 cruncher.set_seq1(ai)
2025-07-02 04:52:32.489 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.489 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.489 # compares by a factor of 3.
2025-07-02 04:52:32.489 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.489 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.489 # of the computation is cached by cruncher
2025-07-02 04:52:32.489 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.489 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.490 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.490 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.490 if best_ratio < cutoff:
2025-07-02 04:52:32.490 # no non-identical "pretty close" pair
2025-07-02 04:52:32.490 if eqi is None:
2025-07-02 04:52:32.490 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.490 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.490 return
2025-07-02 04:52:32.490 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.490 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.490 else:
2025-07-02 04:52:32.490 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.490 eqi = None
2025-07-02 04:52:32.490
2025-07-02 04:52:32.490 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.490 # identical
2025-07-02 04:52:32.490
2025-07-02 04:52:32.490 # pump out diffs from before the synch point
2025-07-02 04:52:32.490 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.490
2025-07-02 04:52:32.491 # do intraline marking on the synch pair
2025-07-02 04:52:32.491 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.491 if eqi is None:
2025-07-02 04:52:32.491 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.491 atags = btags = ""
2025-07-02 04:52:32.491 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.491 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.491 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.491 if tag == 'replace':
2025-07-02 04:52:32.491 atags += '^' * la
2025-07-02 04:52:32.491 btags += '^' * lb
2025-07-02 04:52:32.491 elif tag == 'delete':
2025-07-02 04:52:32.491 atags += '-' * la
2025-07-02 04:52:32.491 elif tag == 'insert':
2025-07-02 04:52:32.491 btags += '+' * lb
2025-07-02 04:52:32.492 elif tag == 'equal':
2025-07-02 04:52:32.492 atags += ' ' * la
2025-07-02 04:52:32.492 btags += ' ' * lb
2025-07-02 04:52:32.492 else:
2025-07-02 04:52:32.492 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.492 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.492 else:
2025-07-02 04:52:32.492 # the synch pair is identical
2025-07-02 04:52:32.492 yield ' ' + aelt
2025-07-02 04:52:32.492
2025-07-02 04:52:32.492 # pump out diffs from after the synch point
2025-07-02 04:52:32.492 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.492
2025-07-02 04:52:32.492 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.492 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.492
2025-07-02 04:52:32.492 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.492 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.492 alo = 235, ahi = 1101
2025-07-02 04:52:32.493 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.493 blo = 235, bhi = 1101
2025-07-02 04:52:32.493
2025-07-02 04:52:32.493 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.493 g = []
2025-07-02 04:52:32.493 if alo < ahi:
2025-07-02 04:52:32.493 if blo < bhi:
2025-07-02 04:52:32.493 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.493 else:
2025-07-02 04:52:32.493 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.493 elif blo < bhi:
2025-07-02 04:52:32.493 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.493
2025-07-02 04:52:32.493 > yield from g
2025-07-02 04:52:32.493
2025-07-02 04:52:32.493 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.493 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.493
2025-07-02 04:52:32.493 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.493 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.493 alo = 235, ahi = 1101
2025-07-02 04:52:32.494 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.494 blo = 235, bhi = 1101
2025-07-02 04:52:32.494
2025-07-02 04:52:32.494 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.494 r"""
2025-07-02 04:52:32.494 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.494 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.494 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.494 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.494
2025-07-02 04:52:32.494 Example:
2025-07-02 04:52:32.494
2025-07-02 04:52:32.494 >>> d = Differ()
2025-07-02 04:52:32.494 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.494 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.494 >>> print(''.join(results), end="")
2025-07-02 04:52:32.494 - abcDefghiJkl
2025-07-02 04:52:32.494 + abcdefGhijkl
2025-07-02 04:52:32.494 """
2025-07-02 04:52:32.495
2025-07-02 04:52:32.495 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.495 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.495 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.495 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.495 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.495
2025-07-02 04:52:32.495 # search for the pair that matches best without being identical
2025-07-02 04:52:32.495 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.495 # on junk -- unless we have to)
2025-07-02 04:52:32.495 for j in range(blo, bhi):
2025-07-02 04:52:32.495 bj = b[j]
2025-07-02 04:52:32.495 cruncher.set_seq2(bj)
2025-07-02 04:52:32.495 for i in range(alo, ahi):
2025-07-02 04:52:32.495 ai = a[i]
2025-07-02 04:52:32.495 if ai == bj:
2025-07-02 04:52:32.495 if eqi is None:
2025-07-02 04:52:32.495 eqi, eqj = i, j
2025-07-02 04:52:32.495 continue
2025-07-02 04:52:32.495 cruncher.set_seq1(ai)
2025-07-02 04:52:32.495 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.495 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.496 # compares by a factor of 3.
2025-07-02 04:52:32.496 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.496 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.496 # of the computation is cached by cruncher
2025-07-02 04:52:32.496 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.496 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.496 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.496 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.496 if best_ratio < cutoff:
2025-07-02 04:52:32.496 # no non-identical "pretty close" pair
2025-07-02 04:52:32.496 if eqi is None:
2025-07-02 04:52:32.496 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.496 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.496 return
2025-07-02 04:52:32.496 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.496 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.496 else:
2025-07-02 04:52:32.496 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.496 eqi = None
2025-07-02 04:52:32.496
2025-07-02 04:52:32.496 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.497 # identical
2025-07-02 04:52:32.497
2025-07-02 04:52:32.497 # pump out diffs from before the synch point
2025-07-02 04:52:32.497 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.497
2025-07-02 04:52:32.497 # do intraline marking on the synch pair
2025-07-02 04:52:32.497 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.497 if eqi is None:
2025-07-02 04:52:32.497 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.497 atags = btags = ""
2025-07-02 04:52:32.497 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.497 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.497 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.497 if tag == 'replace':
2025-07-02 04:52:32.497 atags += '^' * la
2025-07-02 04:52:32.497 btags += '^' * lb
2025-07-02 04:52:32.497 elif tag == 'delete':
2025-07-02 04:52:32.497 atags += '-' * la
2025-07-02 04:52:32.497 elif tag == 'insert':
2025-07-02 04:52:32.497 btags += '+' * lb
2025-07-02 04:52:32.497 elif tag == 'equal':
2025-07-02 04:52:32.498 atags += ' ' * la
2025-07-02 04:52:32.498 btags += ' ' * lb
2025-07-02 04:52:32.498 else:
2025-07-02 04:52:32.498 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.498 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.498 else:
2025-07-02 04:52:32.498 # the synch pair is identical
2025-07-02 04:52:32.498 yield ' ' + aelt
2025-07-02 04:52:32.498
2025-07-02 04:52:32.498 # pump out diffs from after the synch point
2025-07-02 04:52:32.498 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.498
2025-07-02 04:52:32.498 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.498 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.498
2025-07-02 04:52:32.498 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.498 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.498 alo = 236, ahi = 1101
2025-07-02 04:52:32.498 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.499 blo = 236, bhi = 1101
2025-07-02 04:52:32.499
2025-07-02 04:52:32.499 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.499 g = []
2025-07-02 04:52:32.499 if alo < ahi:
2025-07-02 04:52:32.499 if blo < bhi:
2025-07-02 04:52:32.499 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.499 else:
2025-07-02 04:52:32.499 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.499 elif blo < bhi:
2025-07-02 04:52:32.499 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.499
2025-07-02 04:52:32.499 > yield from g
2025-07-02 04:52:32.499
2025-07-02 04:52:32.499 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.499 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.499
2025-07-02 04:52:32.499 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.499 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.499 alo = 236, ahi = 1101
2025-07-02 04:52:32.500 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.500 blo = 236, bhi = 1101
2025-07-02 04:52:32.500
2025-07-02 04:52:32.500 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.500 r"""
2025-07-02 04:52:32.500 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.500 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.500 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.500 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.500
2025-07-02 04:52:32.500 Example:
2025-07-02 04:52:32.500
2025-07-02 04:52:32.500 >>> d = Differ()
2025-07-02 04:52:32.500 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.500 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.500 >>> print(''.join(results), end="")
2025-07-02 04:52:32.500 - abcDefghiJkl
2025-07-02 04:52:32.500 + abcdefGhijkl
2025-07-02 04:52:32.500 """
2025-07-02 04:52:32.501
2025-07-02 04:52:32.501 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.501 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.501 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.501 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.501 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.501
2025-07-02 04:52:32.501 # search for the pair that matches best without being identical
2025-07-02 04:52:32.501 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.501 # on junk -- unless we have to)
2025-07-02 04:52:32.501 for j in range(blo, bhi):
2025-07-02 04:52:32.501 bj = b[j]
2025-07-02 04:52:32.501 cruncher.set_seq2(bj)
2025-07-02 04:52:32.501 for i in range(alo, ahi):
2025-07-02 04:52:32.501 ai = a[i]
2025-07-02 04:52:32.501 if ai == bj:
2025-07-02 04:52:32.501 if eqi is None:
2025-07-02 04:52:32.501 eqi, eqj = i, j
2025-07-02 04:52:32.501 continue
2025-07-02 04:52:32.501 cruncher.set_seq1(ai)
2025-07-02 04:52:32.501 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.502 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.502 # compares by a factor of 3.
2025-07-02 04:52:32.502 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.502 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.502 # of the computation is cached by cruncher
2025-07-02 04:52:32.502 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.502 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.502 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.502 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.502 if best_ratio < cutoff:
2025-07-02 04:52:32.502 # no non-identical "pretty close" pair
2025-07-02 04:52:32.502 if eqi is None:
2025-07-02 04:52:32.502 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.502 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.502 return
2025-07-02 04:52:32.502 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.502 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.502 else:
2025-07-02 04:52:32.502 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.502 eqi = None
2025-07-02 04:52:32.503
2025-07-02 04:52:32.503 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.503 # identical
2025-07-02 04:52:32.503
2025-07-02 04:52:32.503 # pump out diffs from before the synch point
2025-07-02 04:52:32.503 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.503
2025-07-02 04:52:32.503 # do intraline marking on the synch pair
2025-07-02 04:52:32.503 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.503 if eqi is None:
2025-07-02 04:52:32.503 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.503 atags = btags = ""
2025-07-02 04:52:32.503 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.503 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.503 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.503 if tag == 'replace':
2025-07-02 04:52:32.503 atags += '^' * la
2025-07-02 04:52:32.503 btags += '^' * lb
2025-07-02 04:52:32.503 elif tag == 'delete':
2025-07-02 04:52:32.503 atags += '-' * la
2025-07-02 04:52:32.503 elif tag == 'insert':
2025-07-02 04:52:32.504 btags += '+' * lb
2025-07-02 04:52:32.504 elif tag == 'equal':
2025-07-02 04:52:32.504 atags += ' ' * la
2025-07-02 04:52:32.504 btags += ' ' * lb
2025-07-02 04:52:32.504 else:
2025-07-02 04:52:32.504 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.504 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.504 else:
2025-07-02 04:52:32.504 # the synch pair is identical
2025-07-02 04:52:32.504 yield ' ' + aelt
2025-07-02 04:52:32.504
2025-07-02 04:52:32.504 # pump out diffs from after the synch point
2025-07-02 04:52:32.504 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.504
2025-07-02 04:52:32.504 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.504 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.504
2025-07-02 04:52:32.504 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.504 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.504 alo = 237, ahi = 1101
2025-07-02 04:52:32.504 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.505 blo = 237, bhi = 1101
2025-07-02 04:52:32.505
2025-07-02 04:52:32.505 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.505 g = []
2025-07-02 04:52:32.505 if alo < ahi:
2025-07-02 04:52:32.505 if blo < bhi:
2025-07-02 04:52:32.505 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.505 else:
2025-07-02 04:52:32.505 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.505 elif blo < bhi:
2025-07-02 04:52:32.505 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.505
2025-07-02 04:52:32.505 > yield from g
2025-07-02 04:52:32.505
2025-07-02 04:52:32.505 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.505 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.505
2025-07-02 04:52:32.505 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.505 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.505 alo = 237, ahi = 1101
2025-07-02 04:52:32.506 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.506 blo = 237, bhi = 1101
2025-07-02 04:52:32.506
2025-07-02 04:52:32.506 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.506 r"""
2025-07-02 04:52:32.506 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.506 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.506 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.506 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.506
2025-07-02 04:52:32.506 Example:
2025-07-02 04:52:32.506
2025-07-02 04:52:32.506 >>> d = Differ()
2025-07-02 04:52:32.506 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.506 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.506 >>> print(''.join(results), end="")
2025-07-02 04:52:32.506 - abcDefghiJkl
2025-07-02 04:52:32.506 + abcdefGhijkl
2025-07-02 04:52:32.506 """
2025-07-02 04:52:32.507
2025-07-02 04:52:32.507 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.507 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.507 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.507 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.507 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.507
2025-07-02 04:52:32.507 # search for the pair that matches best without being identical
2025-07-02 04:52:32.507 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.507 # on junk -- unless we have to)
2025-07-02 04:52:32.507 for j in range(blo, bhi):
2025-07-02 04:52:32.507 bj = b[j]
2025-07-02 04:52:32.507 cruncher.set_seq2(bj)
2025-07-02 04:52:32.507 for i in range(alo, ahi):
2025-07-02 04:52:32.507 ai = a[i]
2025-07-02 04:52:32.507 if ai == bj:
2025-07-02 04:52:32.507 if eqi is None:
2025-07-02 04:52:32.507 eqi, eqj = i, j
2025-07-02 04:52:32.507 continue
2025-07-02 04:52:32.507 cruncher.set_seq1(ai)
2025-07-02 04:52:32.508 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.508 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.508 # compares by a factor of 3.
2025-07-02 04:52:32.508 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.508 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.508 # of the computation is cached by cruncher
2025-07-02 04:52:32.508 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.508 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.508 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.508 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.508 if best_ratio < cutoff:
2025-07-02 04:52:32.508 # no non-identical "pretty close" pair
2025-07-02 04:52:32.508 if eqi is None:
2025-07-02 04:52:32.508 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.508 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.508 return
2025-07-02 04:52:32.508 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.508 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.508 else:
2025-07-02 04:52:32.508 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.508 eqi = None
2025-07-02 04:52:32.509
2025-07-02 04:52:32.509 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.509 # identical
2025-07-02 04:52:32.509
2025-07-02 04:52:32.509 # pump out diffs from before the synch point
2025-07-02 04:52:32.509 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.509
2025-07-02 04:52:32.509 # do intraline marking on the synch pair
2025-07-02 04:52:32.509 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.509 if eqi is None:
2025-07-02 04:52:32.509 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.509 atags = btags = ""
2025-07-02 04:52:32.509 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.509 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.509 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.509 if tag == 'replace':
2025-07-02 04:52:32.509 atags += '^' * la
2025-07-02 04:52:32.509 btags += '^' * lb
2025-07-02 04:52:32.509 elif tag == 'delete':
2025-07-02 04:52:32.509 atags += '-' * la
2025-07-02 04:52:32.509 elif tag == 'insert':
2025-07-02 04:52:32.510 btags += '+' * lb
2025-07-02 04:52:32.510 elif tag == 'equal':
2025-07-02 04:52:32.510 atags += ' ' * la
2025-07-02 04:52:32.510 btags += ' ' * lb
2025-07-02 04:52:32.510 else:
2025-07-02 04:52:32.510 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.510 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.510 else:
2025-07-02 04:52:32.510 # the synch pair is identical
2025-07-02 04:52:32.510 yield ' ' + aelt
2025-07-02 04:52:32.510
2025-07-02 04:52:32.510 # pump out diffs from after the synch point
2025-07-02 04:52:32.510 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.510
2025-07-02 04:52:32.510 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.510 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.510
2025-07-02 04:52:32.510 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.510 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.510 alo = 238, ahi = 1101
2025-07-02 04:52:32.510 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.511 blo = 238, bhi = 1101
2025-07-02 04:52:32.511
2025-07-02 04:52:32.511 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.511 g = []
2025-07-02 04:52:32.511 if alo < ahi:
2025-07-02 04:52:32.511 if blo < bhi:
2025-07-02 04:52:32.511 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.511 else:
2025-07-02 04:52:32.511 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.511 elif blo < bhi:
2025-07-02 04:52:32.511 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.511
2025-07-02 04:52:32.511 > yield from g
2025-07-02 04:52:32.511
2025-07-02 04:52:32.511 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.511 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.511
2025-07-02 04:52:32.511 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.511 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.511 alo = 238, ahi = 1101
2025-07-02 04:52:32.512 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.512 blo = 238, bhi = 1101
2025-07-02 04:52:32.512
2025-07-02 04:52:32.512 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.512 r"""
2025-07-02 04:52:32.512 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.512 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.512 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.512 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.512
2025-07-02 04:52:32.512 Example:
2025-07-02 04:52:32.512
2025-07-02 04:52:32.512 >>> d = Differ()
2025-07-02 04:52:32.512 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.512 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.512 >>> print(''.join(results), end="")
2025-07-02 04:52:32.512 - abcDefghiJkl
2025-07-02 04:52:32.512 + abcdefGhijkl
2025-07-02 04:52:32.512 """
2025-07-02 04:52:32.513
2025-07-02 04:52:32.513 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.513 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.513 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.513 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.513 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.513
2025-07-02 04:52:32.513 # search for the pair that matches best without being identical
2025-07-02 04:52:32.513 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.513 # on junk -- unless we have to)
2025-07-02 04:52:32.513 for j in range(blo, bhi):
2025-07-02 04:52:32.513 bj = b[j]
2025-07-02 04:52:32.513 cruncher.set_seq2(bj)
2025-07-02 04:52:32.513 for i in range(alo, ahi):
2025-07-02 04:52:32.513 ai = a[i]
2025-07-02 04:52:32.513 if ai == bj:
2025-07-02 04:52:32.513 if eqi is None:
2025-07-02 04:52:32.513 eqi, eqj = i, j
2025-07-02 04:52:32.513 continue
2025-07-02 04:52:32.513 cruncher.set_seq1(ai)
2025-07-02 04:52:32.513 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.514 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.514 # compares by a factor of 3.
2025-07-02 04:52:32.514 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.514 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.514 # of the computation is cached by cruncher
2025-07-02 04:52:32.514 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.514 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.514 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.514 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.514 if best_ratio < cutoff:
2025-07-02 04:52:32.514 # no non-identical "pretty close" pair
2025-07-02 04:52:32.514 if eqi is None:
2025-07-02 04:52:32.514 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.514 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.514 return
2025-07-02 04:52:32.514 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.514 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.514 else:
2025-07-02 04:52:32.514 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.515 eqi = None
2025-07-02 04:52:32.515
2025-07-02 04:52:32.515 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.515 # identical
2025-07-02 04:52:32.515
2025-07-02 04:52:32.515 # pump out diffs from before the synch point
2025-07-02 04:52:32.515 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.515
2025-07-02 04:52:32.515 # do intraline marking on the synch pair
2025-07-02 04:52:32.515 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.515 if eqi is None:
2025-07-02 04:52:32.515 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.515 atags = btags = ""
2025-07-02 04:52:32.515 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.515 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.515 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.515 if tag == 'replace':
2025-07-02 04:52:32.515 atags += '^' * la
2025-07-02 04:52:32.515 btags += '^' * lb
2025-07-02 04:52:32.515 elif tag == 'delete':
2025-07-02 04:52:32.516 atags += '-' * la
2025-07-02 04:52:32.516 elif tag == 'insert':
2025-07-02 04:52:32.516 btags += '+' * lb
2025-07-02 04:52:32.516 elif tag == 'equal':
2025-07-02 04:52:32.516 atags += ' ' * la
2025-07-02 04:52:32.516 btags += ' ' * lb
2025-07-02 04:52:32.516 else:
2025-07-02 04:52:32.516 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.516 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.516 else:
2025-07-02 04:52:32.516 # the synch pair is identical
2025-07-02 04:52:32.516 yield ' ' + aelt
2025-07-02 04:52:32.516
2025-07-02 04:52:32.516 # pump out diffs from after the synch point
2025-07-02 04:52:32.516 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.516
2025-07-02 04:52:32.516 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.516 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.516
2025-07-02 04:52:32.516 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.516 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.517 alo = 239, ahi = 1101
2025-07-02 04:52:32.517 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.517 blo = 239, bhi = 1101
2025-07-02 04:52:32.517
2025-07-02 04:52:32.517 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.517 g = []
2025-07-02 04:52:32.517 if alo < ahi:
2025-07-02 04:52:32.517 if blo < bhi:
2025-07-02 04:52:32.517 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.517 else:
2025-07-02 04:52:32.517 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.517 elif blo < bhi:
2025-07-02 04:52:32.517 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.517
2025-07-02 04:52:32.517 > yield from g
2025-07-02 04:52:32.517
2025-07-02 04:52:32.517 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.517 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.517
2025-07-02 04:52:32.517 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.518 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.518 alo = 239, ahi = 1101
2025-07-02 04:52:32.518 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.518 blo = 239, bhi = 1101
2025-07-02 04:52:32.518
2025-07-02 04:52:32.518 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.518 r"""
2025-07-02 04:52:32.518 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.518 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.518 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.518 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.518
2025-07-02 04:52:32.518 Example:
2025-07-02 04:52:32.518
2025-07-02 04:52:32.518 >>> d = Differ()
2025-07-02 04:52:32.518 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.518 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.518 >>> print(''.join(results), end="")
2025-07-02 04:52:32.518 - abcDefghiJkl
2025-07-02 04:52:32.518 + abcdefGhijkl
2025-07-02 04:52:32.519 """
2025-07-02 04:52:32.519
2025-07-02 04:52:32.519 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.519 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.519 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.519 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.519 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.519
2025-07-02 04:52:32.519 # search for the pair that matches best without being identical
2025-07-02 04:52:32.519 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.519 # on junk -- unless we have to)
2025-07-02 04:52:32.519 for j in range(blo, bhi):
2025-07-02 04:52:32.519 bj = b[j]
2025-07-02 04:52:32.519 cruncher.set_seq2(bj)
2025-07-02 04:52:32.519 for i in range(alo, ahi):
2025-07-02 04:52:32.519 ai = a[i]
2025-07-02 04:52:32.519 if ai == bj:
2025-07-02 04:52:32.519 if eqi is None:
2025-07-02 04:52:32.519 eqi, eqj = i, j
2025-07-02 04:52:32.520 continue
2025-07-02 04:52:32.520 cruncher.set_seq1(ai)
2025-07-02 04:52:32.520 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.520 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.520 # compares by a factor of 3.
2025-07-02 04:52:32.520 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.520 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.520 # of the computation is cached by cruncher
2025-07-02 04:52:32.520 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.520 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.520 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.520 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.520 if best_ratio < cutoff:
2025-07-02 04:52:32.520 # no non-identical "pretty close" pair
2025-07-02 04:52:32.520 if eqi is None:
2025-07-02 04:52:32.520 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.520 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.520 return
2025-07-02 04:52:32.520 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.520 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.520 else:
2025-07-02 04:52:32.521 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.521 eqi = None
2025-07-02 04:52:32.521
2025-07-02 04:52:32.521 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.521 # identical
2025-07-02 04:52:32.521
2025-07-02 04:52:32.521 # pump out diffs from before the synch point
2025-07-02 04:52:32.521 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.521
2025-07-02 04:52:32.521 # do intraline marking on the synch pair
2025-07-02 04:52:32.521 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.521 if eqi is None:
2025-07-02 04:52:32.521 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.521 atags = btags = ""
2025-07-02 04:52:32.521 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.521 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.521 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.521 if tag == 'replace':
2025-07-02 04:52:32.521 atags += '^' * la
2025-07-02 04:52:32.521 btags += '^' * lb
2025-07-02 04:52:32.521 elif tag == 'delete':
2025-07-02 04:52:32.522 atags += '-' * la
2025-07-02 04:52:32.522 elif tag == 'insert':
2025-07-02 04:52:32.522 btags += '+' * lb
2025-07-02 04:52:32.522 elif tag == 'equal':
2025-07-02 04:52:32.522 atags += ' ' * la
2025-07-02 04:52:32.522 btags += ' ' * lb
2025-07-02 04:52:32.522 else:
2025-07-02 04:52:32.522 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.522 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.522 else:
2025-07-02 04:52:32.522 # the synch pair is identical
2025-07-02 04:52:32.522 yield ' ' + aelt
2025-07-02 04:52:32.522
2025-07-02 04:52:32.522 # pump out diffs from after the synch point
2025-07-02 04:52:32.522 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.522
2025-07-02 04:52:32.522 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.522 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.522
2025-07-02 04:52:32.522 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.522 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.523 alo = 240, ahi = 1101
2025-07-02 04:52:32.523 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.523 blo = 240, bhi = 1101
2025-07-02 04:52:32.523
2025-07-02 04:52:32.523 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.523 g = []
2025-07-02 04:52:32.523 if alo < ahi:
2025-07-02 04:52:32.523 if blo < bhi:
2025-07-02 04:52:32.523 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.523 else:
2025-07-02 04:52:32.523 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.523 elif blo < bhi:
2025-07-02 04:52:32.523 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.523
2025-07-02 04:52:32.523 > yield from g
2025-07-02 04:52:32.523
2025-07-02 04:52:32.523 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.523 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.523
2025-07-02 04:52:32.523 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.524 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.524 alo = 240, ahi = 1101
2025-07-02 04:52:32.524 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.524 blo = 240, bhi = 1101
2025-07-02 04:52:32.524
2025-07-02 04:52:32.524 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.524 r"""
2025-07-02 04:52:32.524 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.524 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.524 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.524 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.524
2025-07-02 04:52:32.524 Example:
2025-07-02 04:52:32.524
2025-07-02 04:52:32.524 >>> d = Differ()
2025-07-02 04:52:32.524 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.524 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.524 >>> print(''.join(results), end="")
2025-07-02 04:52:32.524 - abcDefghiJkl
2025-07-02 04:52:32.525 + abcdefGhijkl
2025-07-02 04:52:32.525 """
2025-07-02 04:52:32.525
2025-07-02 04:52:32.525 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.525 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.525 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.525 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.525 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.525
2025-07-02 04:52:32.525 # search for the pair that matches best without being identical
2025-07-02 04:52:32.525 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.525 # on junk -- unless we have to)
2025-07-02 04:52:32.525 for j in range(blo, bhi):
2025-07-02 04:52:32.525 bj = b[j]
2025-07-02 04:52:32.525 cruncher.set_seq2(bj)
2025-07-02 04:52:32.525 for i in range(alo, ahi):
2025-07-02 04:52:32.525 ai = a[i]
2025-07-02 04:52:32.525 if ai == bj:
2025-07-02 04:52:32.525 if eqi is None:
2025-07-02 04:52:32.525 eqi, eqj = i, j
2025-07-02 04:52:32.526 continue
2025-07-02 04:52:32.526 cruncher.set_seq1(ai)
2025-07-02 04:52:32.526 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.526 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.526 # compares by a factor of 3.
2025-07-02 04:52:32.526 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.526 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.526 # of the computation is cached by cruncher
2025-07-02 04:52:32.526 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.526 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.526 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.526 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.526 if best_ratio < cutoff:
2025-07-02 04:52:32.526 # no non-identical "pretty close" pair
2025-07-02 04:52:32.526 if eqi is None:
2025-07-02 04:52:32.526 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.526 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.526 return
2025-07-02 04:52:32.526 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.526 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.527 else:
2025-07-02 04:52:32.527 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.527 eqi = None
2025-07-02 04:52:32.527
2025-07-02 04:52:32.527 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.527 # identical
2025-07-02 04:52:32.527
2025-07-02 04:52:32.527 # pump out diffs from before the synch point
2025-07-02 04:52:32.527 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.527
2025-07-02 04:52:32.527 # do intraline marking on the synch pair
2025-07-02 04:52:32.527 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.527 if eqi is None:
2025-07-02 04:52:32.527 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.527 atags = btags = ""
2025-07-02 04:52:32.527 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.527 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.527 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.527 if tag == 'replace':
2025-07-02 04:52:32.527 atags += '^' * la
2025-07-02 04:52:32.527 btags += '^' * lb
2025-07-02 04:52:32.528 elif tag == 'delete':
2025-07-02 04:52:32.528 atags += '-' * la
2025-07-02 04:52:32.528 elif tag == 'insert':
2025-07-02 04:52:32.528 btags += '+' * lb
2025-07-02 04:52:32.528 elif tag == 'equal':
2025-07-02 04:52:32.528 atags += ' ' * la
2025-07-02 04:52:32.528 btags += ' ' * lb
2025-07-02 04:52:32.528 else:
2025-07-02 04:52:32.528 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.528 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.528 else:
2025-07-02 04:52:32.528 # the synch pair is identical
2025-07-02 04:52:32.528 yield ' ' + aelt
2025-07-02 04:52:32.528
2025-07-02 04:52:32.528 # pump out diffs from after the synch point
2025-07-02 04:52:32.528 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.528
2025-07-02 04:52:32.528 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.528 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.528
2025-07-02 04:52:32.528 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.529 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.529 alo = 241, ahi = 1101
2025-07-02 04:52:32.529 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.529 blo = 241, bhi = 1101
2025-07-02 04:52:32.529
2025-07-02 04:52:32.529 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.529 g = []
2025-07-02 04:52:32.529 if alo < ahi:
2025-07-02 04:52:32.529 if blo < bhi:
2025-07-02 04:52:32.529 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.529 else:
2025-07-02 04:52:32.529 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.529 elif blo < bhi:
2025-07-02 04:52:32.529 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.529
2025-07-02 04:52:32.529 > yield from g
2025-07-02 04:52:32.529
2025-07-02 04:52:32.529 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.529 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.529
2025-07-02 04:52:32.530 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.530 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.530 alo = 241, ahi = 1101
2025-07-02 04:52:32.530 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.530 blo = 241, bhi = 1101
2025-07-02 04:52:32.530
2025-07-02 04:52:32.530 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.530 r"""
2025-07-02 04:52:32.530 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.530 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.530 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.530 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.530
2025-07-02 04:52:32.530 Example:
2025-07-02 04:52:32.530
2025-07-02 04:52:32.530 >>> d = Differ()
2025-07-02 04:52:32.530 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.530 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.530 >>> print(''.join(results), end="")
2025-07-02 04:52:32.530 - abcDefghiJkl
2025-07-02 04:52:32.531 + abcdefGhijkl
2025-07-02 04:52:32.531 """
2025-07-02 04:52:32.531
2025-07-02 04:52:32.531 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.531 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.531 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.531 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.531 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.531
2025-07-02 04:52:32.531 # search for the pair that matches best without being identical
2025-07-02 04:52:32.531 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.531 # on junk -- unless we have to)
2025-07-02 04:52:32.531 for j in range(blo, bhi):
2025-07-02 04:52:32.531 bj = b[j]
2025-07-02 04:52:32.531 cruncher.set_seq2(bj)
2025-07-02 04:52:32.531 for i in range(alo, ahi):
2025-07-02 04:52:32.531 ai = a[i]
2025-07-02 04:52:32.532 if ai == bj:
2025-07-02 04:52:32.532 if eqi is None:
2025-07-02 04:52:32.532 eqi, eqj = i, j
2025-07-02 04:52:32.532 continue
2025-07-02 04:52:32.532 cruncher.set_seq1(ai)
2025-07-02 04:52:32.532 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.532 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.532 # compares by a factor of 3.
2025-07-02 04:52:32.532 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.532 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.532 # of the computation is cached by cruncher
2025-07-02 04:52:32.532 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.532 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.532 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.532 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.532 if best_ratio < cutoff:
2025-07-02 04:52:32.532 # no non-identical "pretty close" pair
2025-07-02 04:52:32.532 if eqi is None:
2025-07-02 04:52:32.532 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.532 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.533 return
2025-07-02 04:52:32.533 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.533 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.533 else:
2025-07-02 04:52:32.533 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.533 eqi = None
2025-07-02 04:52:32.533
2025-07-02 04:52:32.533 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.533 # identical
2025-07-02 04:52:32.533
2025-07-02 04:52:32.533 # pump out diffs from before the synch point
2025-07-02 04:52:32.533 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.533
2025-07-02 04:52:32.533 # do intraline marking on the synch pair
2025-07-02 04:52:32.533 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.533 if eqi is None:
2025-07-02 04:52:32.533 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.533 atags = btags = ""
2025-07-02 04:52:32.533 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.533 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.533 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.534 if tag == 'replace':
2025-07-02 04:52:32.534 atags += '^' * la
2025-07-02 04:52:32.534 btags += '^' * lb
2025-07-02 04:52:32.534 elif tag == 'delete':
2025-07-02 04:52:32.534 atags += '-' * la
2025-07-02 04:52:32.534 elif tag == 'insert':
2025-07-02 04:52:32.534 btags += '+' * lb
2025-07-02 04:52:32.534 elif tag == 'equal':
2025-07-02 04:52:32.534 atags += ' ' * la
2025-07-02 04:52:32.534 btags += ' ' * lb
2025-07-02 04:52:32.534 else:
2025-07-02 04:52:32.534 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.534 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.534 else:
2025-07-02 04:52:32.534 # the synch pair is identical
2025-07-02 04:52:32.534 yield ' ' + aelt
2025-07-02 04:52:32.534
2025-07-02 04:52:32.534 # pump out diffs from after the synch point
2025-07-02 04:52:32.534 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.534
2025-07-02 04:52:32.534 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.535 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.535
2025-07-02 04:52:32.535 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.535 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.535 alo = 242, ahi = 1101
2025-07-02 04:52:32.535 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.535 blo = 242, bhi = 1101
2025-07-02 04:52:32.535
2025-07-02 04:52:32.535 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.535 g = []
2025-07-02 04:52:32.535 if alo < ahi:
2025-07-02 04:52:32.535 if blo < bhi:
2025-07-02 04:52:32.535 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.535 else:
2025-07-02 04:52:32.535 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.535 elif blo < bhi:
2025-07-02 04:52:32.535 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.535
2025-07-02 04:52:32.535 > yield from g
2025-07-02 04:52:32.535
2025-07-02 04:52:32.536 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.536 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.536
2025-07-02 04:52:32.536 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.536 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.536 alo = 242, ahi = 1101
2025-07-02 04:52:32.536 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.536 blo = 242, bhi = 1101
2025-07-02 04:52:32.536
2025-07-02 04:52:32.536 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.536 r"""
2025-07-02 04:52:32.536 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.536 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.536 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.536 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.536
2025-07-02 04:52:32.536 Example:
2025-07-02 04:52:32.536
2025-07-02 04:52:32.536 >>> d = Differ()
2025-07-02 04:52:32.536 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.536 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.537 >>> print(''.join(results), end="")
2025-07-02 04:52:32.537 - abcDefghiJkl
2025-07-02 04:52:32.537 + abcdefGhijkl
2025-07-02 04:52:32.537 """
2025-07-02 04:52:32.537
2025-07-02 04:52:32.537 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.537 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.537 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.537 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.537 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.537
2025-07-02 04:52:32.537 # search for the pair that matches best without being identical
2025-07-02 04:52:32.537 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.537 # on junk -- unless we have to)
2025-07-02 04:52:32.537 for j in range(blo, bhi):
2025-07-02 04:52:32.537 bj = b[j]
2025-07-02 04:52:32.537 cruncher.set_seq2(bj)
2025-07-02 04:52:32.537 for i in range(alo, ahi):
2025-07-02 04:52:32.538 ai = a[i]
2025-07-02 04:52:32.538 if ai == bj:
2025-07-02 04:52:32.538 if eqi is None:
2025-07-02 04:52:32.538 eqi, eqj = i, j
2025-07-02 04:52:32.538 continue
2025-07-02 04:52:32.538 cruncher.set_seq1(ai)
2025-07-02 04:52:32.538 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.538 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.538 # compares by a factor of 3.
2025-07-02 04:52:32.538 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.538 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.538 # of the computation is cached by cruncher
2025-07-02 04:52:32.538 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.538 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.538 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.538 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.538 if best_ratio < cutoff:
2025-07-02 04:52:32.538 # no non-identical "pretty close" pair
2025-07-02 04:52:32.538 if eqi is None:
2025-07-02 04:52:32.538 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.538 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.539 return
2025-07-02 04:52:32.539 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.539 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.539 else:
2025-07-02 04:52:32.539 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.539 eqi = None
2025-07-02 04:52:32.539
2025-07-02 04:52:32.539 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.539 # identical
2025-07-02 04:52:32.539
2025-07-02 04:52:32.539 # pump out diffs from before the synch point
2025-07-02 04:52:32.539 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.539
2025-07-02 04:52:32.539 # do intraline marking on the synch pair
2025-07-02 04:52:32.539 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.539 if eqi is None:
2025-07-02 04:52:32.539 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.539 atags = btags = ""
2025-07-02 04:52:32.539 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.539 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.540 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.540 if tag == 'replace':
2025-07-02 04:52:32.540 atags += '^' * la
2025-07-02 04:52:32.540 btags += '^' * lb
2025-07-02 04:52:32.540 elif tag == 'delete':
2025-07-02 04:52:32.540 atags += '-' * la
2025-07-02 04:52:32.540 elif tag == 'insert':
2025-07-02 04:52:32.540 btags += '+' * lb
2025-07-02 04:52:32.540 elif tag == 'equal':
2025-07-02 04:52:32.540 atags += ' ' * la
2025-07-02 04:52:32.540 btags += ' ' * lb
2025-07-02 04:52:32.540 else:
2025-07-02 04:52:32.540 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.540 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.540 else:
2025-07-02 04:52:32.540 # the synch pair is identical
2025-07-02 04:52:32.540 yield ' ' + aelt
2025-07-02 04:52:32.540
2025-07-02 04:52:32.540 # pump out diffs from after the synch point
2025-07-02 04:52:32.540 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.540
2025-07-02 04:52:32.541 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.541 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.541
2025-07-02 04:52:32.541 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.541 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.541 alo = 243, ahi = 1101
2025-07-02 04:52:32.541 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.541 blo = 243, bhi = 1101
2025-07-02 04:52:32.541
2025-07-02 04:52:32.541 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.541 g = []
2025-07-02 04:52:32.541 if alo < ahi:
2025-07-02 04:52:32.541 if blo < bhi:
2025-07-02 04:52:32.541 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.541 else:
2025-07-02 04:52:32.541 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.541 elif blo < bhi:
2025-07-02 04:52:32.541 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.541
2025-07-02 04:52:32.541 > yield from g
2025-07-02 04:52:32.542
2025-07-02 04:52:32.542 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.542 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.542
2025-07-02 04:52:32.542 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.542 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.542 alo = 243, ahi = 1101
2025-07-02 04:52:32.542 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.542 blo = 243, bhi = 1101
2025-07-02 04:52:32.542
2025-07-02 04:52:32.542 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.542 r"""
2025-07-02 04:52:32.542 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.542 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.542 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.542 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.542
2025-07-02 04:52:32.542 Example:
2025-07-02 04:52:32.542
2025-07-02 04:52:32.542 >>> d = Differ()
2025-07-02 04:52:32.542 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.543 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.543 >>> print(''.join(results), end="")
2025-07-02 04:52:32.543 - abcDefghiJkl
2025-07-02 04:52:32.543 + abcdefGhijkl
2025-07-02 04:52:32.543 """
2025-07-02 04:52:32.543
2025-07-02 04:52:32.543 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.543 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.543 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.543 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.543 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.543
2025-07-02 04:52:32.543 # search for the pair that matches best without being identical
2025-07-02 04:52:32.543 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.543 # on junk -- unless we have to)
2025-07-02 04:52:32.543 for j in range(blo, bhi):
2025-07-02 04:52:32.543 bj = b[j]
2025-07-02 04:52:32.543 cruncher.set_seq2(bj)
2025-07-02 04:52:32.544 for i in range(alo, ahi):
2025-07-02 04:52:32.544 ai = a[i]
2025-07-02 04:52:32.544 if ai == bj:
2025-07-02 04:52:32.544 if eqi is None:
2025-07-02 04:52:32.544 eqi, eqj = i, j
2025-07-02 04:52:32.544 continue
2025-07-02 04:52:32.544 cruncher.set_seq1(ai)
2025-07-02 04:52:32.544 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.544 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.544 # compares by a factor of 3.
2025-07-02 04:52:32.544 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.544 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.544 # of the computation is cached by cruncher
2025-07-02 04:52:32.544 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.544 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.544 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.544 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.544 if best_ratio < cutoff:
2025-07-02 04:52:32.544 # no non-identical "pretty close" pair
2025-07-02 04:52:32.544 if eqi is None:
2025-07-02 04:52:32.544 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.545 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.545 return
2025-07-02 04:52:32.545 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.545 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.545 else:
2025-07-02 04:52:32.545 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.545 eqi = None
2025-07-02 04:52:32.545
2025-07-02 04:52:32.545 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.545 # identical
2025-07-02 04:52:32.545
2025-07-02 04:52:32.545 # pump out diffs from before the synch point
2025-07-02 04:52:32.545 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.545
2025-07-02 04:52:32.545 # do intraline marking on the synch pair
2025-07-02 04:52:32.545 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.545 if eqi is None:
2025-07-02 04:52:32.545 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.545 atags = btags = ""
2025-07-02 04:52:32.545 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.545 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.545 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.546 if tag == 'replace':
2025-07-02 04:52:32.546 atags += '^' * la
2025-07-02 04:52:32.546 btags += '^' * lb
2025-07-02 04:52:32.546 elif tag == 'delete':
2025-07-02 04:52:32.546 atags += '-' * la
2025-07-02 04:52:32.546 elif tag == 'insert':
2025-07-02 04:52:32.546 btags += '+' * lb
2025-07-02 04:52:32.546 elif tag == 'equal':
2025-07-02 04:52:32.546 atags += ' ' * la
2025-07-02 04:52:32.546 btags += ' ' * lb
2025-07-02 04:52:32.546 else:
2025-07-02 04:52:32.546 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.546 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.546 else:
2025-07-02 04:52:32.546 # the synch pair is identical
2025-07-02 04:52:32.546 yield ' ' + aelt
2025-07-02 04:52:32.546
2025-07-02 04:52:32.546 # pump out diffs from after the synch point
2025-07-02 04:52:32.547 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.547
2025-07-02 04:52:32.547 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.547 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.547
2025-07-02 04:52:32.547 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.547 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.547 alo = 246, ahi = 1101
2025-07-02 04:52:32.547 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.547 blo = 246, bhi = 1101
2025-07-02 04:52:32.547
2025-07-02 04:52:32.547 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.547 g = []
2025-07-02 04:52:32.547 if alo < ahi:
2025-07-02 04:52:32.547 if blo < bhi:
2025-07-02 04:52:32.547 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.547 else:
2025-07-02 04:52:32.547 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.547 elif blo < bhi:
2025-07-02 04:52:32.547 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.547
2025-07-02 04:52:32.548 > yield from g
2025-07-02 04:52:32.548
2025-07-02 04:52:32.548 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.548 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.548
2025-07-02 04:52:32.548 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.548 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.548 alo = 246, ahi = 1101
2025-07-02 04:52:32.548 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.548 blo = 246, bhi = 1101
2025-07-02 04:52:32.548
2025-07-02 04:52:32.548 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.548 r"""
2025-07-02 04:52:32.548 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.548 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.548 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.548 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.548
2025-07-02 04:52:32.548 Example:
2025-07-02 04:52:32.549
2025-07-02 04:52:32.549 >>> d = Differ()
2025-07-02 04:52:32.549 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.549 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.549 >>> print(''.join(results), end="")
2025-07-02 04:52:32.549 - abcDefghiJkl
2025-07-02 04:52:32.549 + abcdefGhijkl
2025-07-02 04:52:32.549 """
2025-07-02 04:52:32.549
2025-07-02 04:52:32.549 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.549 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.549 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.549 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.549 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.549
2025-07-02 04:52:32.549 # search for the pair that matches best without being identical
2025-07-02 04:52:32.549 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.549 # on junk -- unless we have to)
2025-07-02 04:52:32.549 for j in range(blo, bhi):
2025-07-02 04:52:32.550 bj = b[j]
2025-07-02 04:52:32.550 cruncher.set_seq2(bj)
2025-07-02 04:52:32.550 for i in range(alo, ahi):
2025-07-02 04:52:32.550 ai = a[i]
2025-07-02 04:52:32.550 if ai == bj:
2025-07-02 04:52:32.550 if eqi is None:
2025-07-02 04:52:32.550 eqi, eqj = i, j
2025-07-02 04:52:32.550 continue
2025-07-02 04:52:32.550 cruncher.set_seq1(ai)
2025-07-02 04:52:32.550 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.550 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.550 # compares by a factor of 3.
2025-07-02 04:52:32.550 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.550 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.550 # of the computation is cached by cruncher
2025-07-02 04:52:32.550 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.550 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.550 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.550 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.550 if best_ratio < cutoff:
2025-07-02 04:52:32.550 # no non-identical "pretty close" pair
2025-07-02 04:52:32.551 if eqi is None:
2025-07-02 04:52:32.551 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.551 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.551 return
2025-07-02 04:52:32.551 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.551 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.551 else:
2025-07-02 04:52:32.551 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.551 eqi = None
2025-07-02 04:52:32.551
2025-07-02 04:52:32.551 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.551 # identical
2025-07-02 04:52:32.551
2025-07-02 04:52:32.551 # pump out diffs from before the synch point
2025-07-02 04:52:32.551 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.551
2025-07-02 04:52:32.551 # do intraline marking on the synch pair
2025-07-02 04:52:32.551 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.551 if eqi is None:
2025-07-02 04:52:32.551 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.551 atags = btags = ""
2025-07-02 04:52:32.552 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.552 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.552 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.552 if tag == 'replace':
2025-07-02 04:52:32.552 atags += '^' * la
2025-07-02 04:52:32.552 btags += '^' * lb
2025-07-02 04:52:32.552 elif tag == 'delete':
2025-07-02 04:52:32.552 atags += '-' * la
2025-07-02 04:52:32.552 elif tag == 'insert':
2025-07-02 04:52:32.552 btags += '+' * lb
2025-07-02 04:52:32.552 elif tag == 'equal':
2025-07-02 04:52:32.552 atags += ' ' * la
2025-07-02 04:52:32.552 btags += ' ' * lb
2025-07-02 04:52:32.552 else:
2025-07-02 04:52:32.552 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.552 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.552 else:
2025-07-02 04:52:32.552 # the synch pair is identical
2025-07-02 04:52:32.552 yield ' ' + aelt
2025-07-02 04:52:32.552
2025-07-02 04:52:32.552 # pump out diffs from after the synch point
2025-07-02 04:52:32.552 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.553
2025-07-02 04:52:32.553 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.553 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.553
2025-07-02 04:52:32.553 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.553 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.553 alo = 247, ahi = 1101
2025-07-02 04:52:32.553 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.553 blo = 247, bhi = 1101
2025-07-02 04:52:32.553
2025-07-02 04:52:32.553 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.553 g = []
2025-07-02 04:52:32.553 if alo < ahi:
2025-07-02 04:52:32.553 if blo < bhi:
2025-07-02 04:52:32.553 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.553 else:
2025-07-02 04:52:32.553 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.553 elif blo < bhi:
2025-07-02 04:52:32.553 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.553
2025-07-02 04:52:32.553 > yield from g
2025-07-02 04:52:32.554
2025-07-02 04:52:32.554 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.554 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.554
2025-07-02 04:52:32.554 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.554 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.554 alo = 247, ahi = 1101
2025-07-02 04:52:32.554 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.554 blo = 247, bhi = 1101
2025-07-02 04:52:32.554
2025-07-02 04:52:32.554 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.554 r"""
2025-07-02 04:52:32.554 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.554 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.554 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.554 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.554
2025-07-02 04:52:32.554 Example:
2025-07-02 04:52:32.554
2025-07-02 04:52:32.554 >>> d = Differ()
2025-07-02 04:52:32.554 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.554 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.555 >>> print(''.join(results), end="")
2025-07-02 04:52:32.555 - abcDefghiJkl
2025-07-02 04:52:32.555 + abcdefGhijkl
2025-07-02 04:52:32.555 """
2025-07-02 04:52:32.555
2025-07-02 04:52:32.555 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.555 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.555 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.555 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.555 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.555
2025-07-02 04:52:32.555 # search for the pair that matches best without being identical
2025-07-02 04:52:32.555 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.555 # on junk -- unless we have to)
2025-07-02 04:52:32.555 for j in range(blo, bhi):
2025-07-02 04:52:32.555 bj = b[j]
2025-07-02 04:52:32.555 cruncher.set_seq2(bj)
2025-07-02 04:52:32.555 for i in range(alo, ahi):
2025-07-02 04:52:32.555 ai = a[i]
2025-07-02 04:52:32.556 if ai == bj:
2025-07-02 04:52:32.556 if eqi is None:
2025-07-02 04:52:32.556 eqi, eqj = i, j
2025-07-02 04:52:32.556 continue
2025-07-02 04:52:32.556 cruncher.set_seq1(ai)
2025-07-02 04:52:32.556 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.556 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.556 # compares by a factor of 3.
2025-07-02 04:52:32.556 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.556 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.556 # of the computation is cached by cruncher
2025-07-02 04:52:32.556 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.556 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.556 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.556 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.556 if best_ratio < cutoff:
2025-07-02 04:52:32.556 # no non-identical "pretty close" pair
2025-07-02 04:52:32.556 if eqi is None:
2025-07-02 04:52:32.556 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.557 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.557 return
2025-07-02 04:52:32.557 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.557 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.557 else:
2025-07-02 04:52:32.557 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.557 eqi = None
2025-07-02 04:52:32.557
2025-07-02 04:52:32.557 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.557 # identical
2025-07-02 04:52:32.557
2025-07-02 04:52:32.557 # pump out diffs from before the synch point
2025-07-02 04:52:32.557 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.557
2025-07-02 04:52:32.557 # do intraline marking on the synch pair
2025-07-02 04:52:32.557 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.557 if eqi is None:
2025-07-02 04:52:32.557 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.557 atags = btags = ""
2025-07-02 04:52:32.557 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.557 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.558 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.558 if tag == 'replace':
2025-07-02 04:52:32.558 atags += '^' * la
2025-07-02 04:52:32.558 btags += '^' * lb
2025-07-02 04:52:32.558 elif tag == 'delete':
2025-07-02 04:52:32.558 atags += '-' * la
2025-07-02 04:52:32.558 elif tag == 'insert':
2025-07-02 04:52:32.558 btags += '+' * lb
2025-07-02 04:52:32.558 elif tag == 'equal':
2025-07-02 04:52:32.558 atags += ' ' * la
2025-07-02 04:52:32.558 btags += ' ' * lb
2025-07-02 04:52:32.558 else:
2025-07-02 04:52:32.558 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.558 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.558 else:
2025-07-02 04:52:32.558 # the synch pair is identical
2025-07-02 04:52:32.558 yield ' ' + aelt
2025-07-02 04:52:32.558
2025-07-02 04:52:32.558 # pump out diffs from after the synch point
2025-07-02 04:52:32.558 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.559
2025-07-02 04:52:32.559 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.559 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.559
2025-07-02 04:52:32.559 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.559 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.559 alo = 248, ahi = 1101
2025-07-02 04:52:32.559 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.559 blo = 248, bhi = 1101
2025-07-02 04:52:32.559
2025-07-02 04:52:32.559 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.559 g = []
2025-07-02 04:52:32.559 if alo < ahi:
2025-07-02 04:52:32.559 if blo < bhi:
2025-07-02 04:52:32.559 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.559 else:
2025-07-02 04:52:32.559 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.559 elif blo < bhi:
2025-07-02 04:52:32.559 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.559
2025-07-02 04:52:32.560 > yield from g
2025-07-02 04:52:32.560
2025-07-02 04:52:32.560 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.560 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.560
2025-07-02 04:52:32.560 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.560 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.560 alo = 248, ahi = 1101
2025-07-02 04:52:32.560 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.560 blo = 248, bhi = 1101
2025-07-02 04:52:32.560
2025-07-02 04:52:32.560 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.560 r"""
2025-07-02 04:52:32.560 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.560 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.560 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.560 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.560
2025-07-02 04:52:32.560 Example:
2025-07-02 04:52:32.560
2025-07-02 04:52:32.560 >>> d = Differ()
2025-07-02 04:52:32.561 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.561 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.561 >>> print(''.join(results), end="")
2025-07-02 04:52:32.561 - abcDefghiJkl
2025-07-02 04:52:32.561 + abcdefGhijkl
2025-07-02 04:52:32.561 """
2025-07-02 04:52:32.561
2025-07-02 04:52:32.561 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.561 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.561 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.561 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.561 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.561
2025-07-02 04:52:32.561 # search for the pair that matches best without being identical
2025-07-02 04:52:32.561 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.561 # on junk -- unless we have to)
2025-07-02 04:52:32.561 for j in range(blo, bhi):
2025-07-02 04:52:32.561 bj = b[j]
2025-07-02 04:52:32.561 cruncher.set_seq2(bj)
2025-07-02 04:52:32.561 for i in range(alo, ahi):
2025-07-02 04:52:32.562 ai = a[i]
2025-07-02 04:52:32.562 if ai == bj:
2025-07-02 04:52:32.562 if eqi is None:
2025-07-02 04:52:32.562 eqi, eqj = i, j
2025-07-02 04:52:32.562 continue
2025-07-02 04:52:32.562 cruncher.set_seq1(ai)
2025-07-02 04:52:32.562 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.562 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.562 # compares by a factor of 3.
2025-07-02 04:52:32.562 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.562 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.562 # of the computation is cached by cruncher
2025-07-02 04:52:32.562 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.562 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.562 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.562 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.562 if best_ratio < cutoff:
2025-07-02 04:52:32.562 # no non-identical "pretty close" pair
2025-07-02 04:52:32.563 if eqi is None:
2025-07-02 04:52:32.563 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.563 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.563 return
2025-07-02 04:52:32.563 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.563 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.563 else:
2025-07-02 04:52:32.563 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.563 eqi = None
2025-07-02 04:52:32.563
2025-07-02 04:52:32.563 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.563 # identical
2025-07-02 04:52:32.563
2025-07-02 04:52:32.563 # pump out diffs from before the synch point
2025-07-02 04:52:32.563 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.563
2025-07-02 04:52:32.563 # do intraline marking on the synch pair
2025-07-02 04:52:32.563 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.563 if eqi is None:
2025-07-02 04:52:32.563 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.563 atags = btags = ""
2025-07-02 04:52:32.564 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.564 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.564 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.564 if tag == 'replace':
2025-07-02 04:52:32.564 atags += '^' * la
2025-07-02 04:52:32.564 btags += '^' * lb
2025-07-02 04:52:32.564 elif tag == 'delete':
2025-07-02 04:52:32.564 atags += '-' * la
2025-07-02 04:52:32.564 elif tag == 'insert':
2025-07-02 04:52:32.564 btags += '+' * lb
2025-07-02 04:52:32.564 elif tag == 'equal':
2025-07-02 04:52:32.564 atags += ' ' * la
2025-07-02 04:52:32.564 btags += ' ' * lb
2025-07-02 04:52:32.564 else:
2025-07-02 04:52:32.564 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.564 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.564 else:
2025-07-02 04:52:32.564 # the synch pair is identical
2025-07-02 04:52:32.564 yield ' ' + aelt
2025-07-02 04:52:32.564
2025-07-02 04:52:32.565 # pump out diffs from after the synch point
2025-07-02 04:52:32.565 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.565
2025-07-02 04:52:32.565 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.565 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.565
2025-07-02 04:52:32.565 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.565 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.565 alo = 249, ahi = 1101
2025-07-02 04:52:32.565 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.565 blo = 249, bhi = 1101
2025-07-02 04:52:32.565
2025-07-02 04:52:32.565 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.565 g = []
2025-07-02 04:52:32.565 if alo < ahi:
2025-07-02 04:52:32.565 if blo < bhi:
2025-07-02 04:52:32.565 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.565 else:
2025-07-02 04:52:32.565 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.565 elif blo < bhi:
2025-07-02 04:52:32.565 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.566
2025-07-02 04:52:32.566 > yield from g
2025-07-02 04:52:32.566
2025-07-02 04:52:32.566 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.566 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.566
2025-07-02 04:52:32.566 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.566 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.566 alo = 249, ahi = 1101
2025-07-02 04:52:32.566 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.566 blo = 249, bhi = 1101
2025-07-02 04:52:32.566
2025-07-02 04:52:32.566 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.566 r"""
2025-07-02 04:52:32.566 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.566 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.566 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.566 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.566
2025-07-02 04:52:32.566 Example:
2025-07-02 04:52:32.567
2025-07-02 04:52:32.567 >>> d = Differ()
2025-07-02 04:52:32.567 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.567 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.567 >>> print(''.join(results), end="")
2025-07-02 04:52:32.567 - abcDefghiJkl
2025-07-02 04:52:32.567 + abcdefGhijkl
2025-07-02 04:52:32.567 """
2025-07-02 04:52:32.567
2025-07-02 04:52:32.567 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.567 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.567 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.567 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.567 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.567
2025-07-02 04:52:32.567 # search for the pair that matches best without being identical
2025-07-02 04:52:32.567 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.567 # on junk -- unless we have to)
2025-07-02 04:52:32.567 for j in range(blo, bhi):
2025-07-02 04:52:32.568 bj = b[j]
2025-07-02 04:52:32.568 cruncher.set_seq2(bj)
2025-07-02 04:52:32.568 for i in range(alo, ahi):
2025-07-02 04:52:32.568 ai = a[i]
2025-07-02 04:52:32.568 if ai == bj:
2025-07-02 04:52:32.568 if eqi is None:
2025-07-02 04:52:32.568 eqi, eqj = i, j
2025-07-02 04:52:32.568 continue
2025-07-02 04:52:32.568 cruncher.set_seq1(ai)
2025-07-02 04:52:32.568 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.568 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.568 # compares by a factor of 3.
2025-07-02 04:52:32.568 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.568 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.568 # of the computation is cached by cruncher
2025-07-02 04:52:32.568 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.568 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.568 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.568 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.568 if best_ratio < cutoff:
2025-07-02 04:52:32.569 # no non-identical "pretty close" pair
2025-07-02 04:52:32.569 if eqi is None:
2025-07-02 04:52:32.569 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.569 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.569 return
2025-07-02 04:52:32.569 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.569 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.569 else:
2025-07-02 04:52:32.569 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.569 eqi = None
2025-07-02 04:52:32.569
2025-07-02 04:52:32.569 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.569 # identical
2025-07-02 04:52:32.569
2025-07-02 04:52:32.569 # pump out diffs from before the synch point
2025-07-02 04:52:32.569 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.569
2025-07-02 04:52:32.569 # do intraline marking on the synch pair
2025-07-02 04:52:32.569 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.569 if eqi is None:
2025-07-02 04:52:32.569 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.570 atags = btags = ""
2025-07-02 04:52:32.570 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.570 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.570 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.570 if tag == 'replace':
2025-07-02 04:52:32.570 atags += '^' * la
2025-07-02 04:52:32.570 btags += '^' * lb
2025-07-02 04:52:32.570 elif tag == 'delete':
2025-07-02 04:52:32.570 atags += '-' * la
2025-07-02 04:52:32.570 elif tag == 'insert':
2025-07-02 04:52:32.570 btags += '+' * lb
2025-07-02 04:52:32.570 elif tag == 'equal':
2025-07-02 04:52:32.570 atags += ' ' * la
2025-07-02 04:52:32.570 btags += ' ' * lb
2025-07-02 04:52:32.570 else:
2025-07-02 04:52:32.570 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.570 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.570 else:
2025-07-02 04:52:32.570 # the synch pair is identical
2025-07-02 04:52:32.570 yield ' ' + aelt
2025-07-02 04:52:32.570
2025-07-02 04:52:32.571 # pump out diffs from after the synch point
2025-07-02 04:52:32.571 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.571
2025-07-02 04:52:32.571 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.571 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.571
2025-07-02 04:52:32.571 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.571 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.571 alo = 250, ahi = 1101
2025-07-02 04:52:32.571 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.571 blo = 250, bhi = 1101
2025-07-02 04:52:32.571
2025-07-02 04:52:32.571 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.571 g = []
2025-07-02 04:52:32.571 if alo < ahi:
2025-07-02 04:52:32.571 if blo < bhi:
2025-07-02 04:52:32.571 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.571 else:
2025-07-02 04:52:32.571 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.571 elif blo < bhi:
2025-07-02 04:52:32.572 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.572
2025-07-02 04:52:32.572 > yield from g
2025-07-02 04:52:32.572
2025-07-02 04:52:32.572 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.572 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.572
2025-07-02 04:52:32.572 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.572 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.572 alo = 250, ahi = 1101
2025-07-02 04:52:32.572 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.572 blo = 250, bhi = 1101
2025-07-02 04:52:32.572
2025-07-02 04:52:32.572 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.572 r"""
2025-07-02 04:52:32.572 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.572 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.572 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.572 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.572
2025-07-02 04:52:32.572 Example:
2025-07-02 04:52:32.573
2025-07-02 04:52:32.573 >>> d = Differ()
2025-07-02 04:52:32.573 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.573 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.573 >>> print(''.join(results), end="")
2025-07-02 04:52:32.573 - abcDefghiJkl
2025-07-02 04:52:32.573 + abcdefGhijkl
2025-07-02 04:52:32.573 """
2025-07-02 04:52:32.573
2025-07-02 04:52:32.573 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.573 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.573 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.573 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.573 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.573
2025-07-02 04:52:32.573 # search for the pair that matches best without being identical
2025-07-02 04:52:32.573 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.574 # on junk -- unless we have to)
2025-07-02 04:52:32.574 for j in range(blo, bhi):
2025-07-02 04:52:32.574 bj = b[j]
2025-07-02 04:52:32.574 cruncher.set_seq2(bj)
2025-07-02 04:52:32.574 for i in range(alo, ahi):
2025-07-02 04:52:32.574 ai = a[i]
2025-07-02 04:52:32.574 if ai == bj:
2025-07-02 04:52:32.574 if eqi is None:
2025-07-02 04:52:32.574 eqi, eqj = i, j
2025-07-02 04:52:32.574 continue
2025-07-02 04:52:32.574 cruncher.set_seq1(ai)
2025-07-02 04:52:32.574 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.574 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.574 # compares by a factor of 3.
2025-07-02 04:52:32.574 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.574 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.574 # of the computation is cached by cruncher
2025-07-02 04:52:32.574 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.574 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.574 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.575 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.575 if best_ratio < cutoff:
2025-07-02 04:52:32.575 # no non-identical "pretty close" pair
2025-07-02 04:52:32.575 if eqi is None:
2025-07-02 04:52:32.575 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.575 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.575 return
2025-07-02 04:52:32.575 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.575 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.575 else:
2025-07-02 04:52:32.575 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.575 eqi = None
2025-07-02 04:52:32.575
2025-07-02 04:52:32.575 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.575 # identical
2025-07-02 04:52:32.575
2025-07-02 04:52:32.575 # pump out diffs from before the synch point
2025-07-02 04:52:32.575 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.575
2025-07-02 04:52:32.575 # do intraline marking on the synch pair
2025-07-02 04:52:32.575 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.575 if eqi is None:
2025-07-02 04:52:32.576 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.576 atags = btags = ""
2025-07-02 04:52:32.576 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.576 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.576 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.576 if tag == 'replace':
2025-07-02 04:52:32.576 atags += '^' * la
2025-07-02 04:52:32.576 btags += '^' * lb
2025-07-02 04:52:32.576 elif tag == 'delete':
2025-07-02 04:52:32.576 atags += '-' * la
2025-07-02 04:52:32.576 elif tag == 'insert':
2025-07-02 04:52:32.576 btags += '+' * lb
2025-07-02 04:52:32.576 elif tag == 'equal':
2025-07-02 04:52:32.576 atags += ' ' * la
2025-07-02 04:52:32.576 btags += ' ' * lb
2025-07-02 04:52:32.576 else:
2025-07-02 04:52:32.576 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.576 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.576 else:
2025-07-02 04:52:32.576 # the synch pair is identical
2025-07-02 04:52:32.576 yield ' ' + aelt
2025-07-02 04:52:32.577
2025-07-02 04:52:32.577 # pump out diffs from after the synch point
2025-07-02 04:52:32.577 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.577
2025-07-02 04:52:32.577 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.577 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.577
2025-07-02 04:52:32.577 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.577 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.577 alo = 251, ahi = 1101
2025-07-02 04:52:32.577 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.577 blo = 251, bhi = 1101
2025-07-02 04:52:32.577
2025-07-02 04:52:32.577 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.577 g = []
2025-07-02 04:52:32.577 if alo < ahi:
2025-07-02 04:52:32.577 if blo < bhi:
2025-07-02 04:52:32.577 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.577 else:
2025-07-02 04:52:32.577 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.577 elif blo < bhi:
2025-07-02 04:52:32.577 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.578
2025-07-02 04:52:32.578 > yield from g
2025-07-02 04:52:32.578
2025-07-02 04:52:32.578 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.578 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.578
2025-07-02 04:52:32.578 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.578 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.578 alo = 251, ahi = 1101
2025-07-02 04:52:32.578 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.578 blo = 251, bhi = 1101
2025-07-02 04:52:32.578
2025-07-02 04:52:32.578 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.578 r"""
2025-07-02 04:52:32.578 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.578 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.578 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.578 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.578
2025-07-02 04:52:32.579 Example:
2025-07-02 04:52:32.579
2025-07-02 04:52:32.579 >>> d = Differ()
2025-07-02 04:52:32.579 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.579 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.579 >>> print(''.join(results), end="")
2025-07-02 04:52:32.579 - abcDefghiJkl
2025-07-02 04:52:32.579 + abcdefGhijkl
2025-07-02 04:52:32.579 """
2025-07-02 04:52:32.579
2025-07-02 04:52:32.579 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.579 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.579 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.579 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.579 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.579
2025-07-02 04:52:32.579 # search for the pair that matches best without being identical
2025-07-02 04:52:32.579 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.579 # on junk -- unless we have to)
2025-07-02 04:52:32.580 for j in range(blo, bhi):
2025-07-02 04:52:32.580 bj = b[j]
2025-07-02 04:52:32.580 cruncher.set_seq2(bj)
2025-07-02 04:52:32.580 for i in range(alo, ahi):
2025-07-02 04:52:32.580 ai = a[i]
2025-07-02 04:52:32.580 if ai == bj:
2025-07-02 04:52:32.580 if eqi is None:
2025-07-02 04:52:32.580 eqi, eqj = i, j
2025-07-02 04:52:32.580 continue
2025-07-02 04:52:32.580 cruncher.set_seq1(ai)
2025-07-02 04:52:32.580 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.580 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.580 # compares by a factor of 3.
2025-07-02 04:52:32.580 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.580 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.580 # of the computation is cached by cruncher
2025-07-02 04:52:32.580 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.580 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.580 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.580 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.580 if best_ratio < cutoff:
2025-07-02 04:52:32.581 # no non-identical "pretty close" pair
2025-07-02 04:52:32.581 if eqi is None:
2025-07-02 04:52:32.581 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.581 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.581 return
2025-07-02 04:52:32.581 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.581 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.581 else:
2025-07-02 04:52:32.581 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.581 eqi = None
2025-07-02 04:52:32.581
2025-07-02 04:52:32.581 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.581 # identical
2025-07-02 04:52:32.581
2025-07-02 04:52:32.581 # pump out diffs from before the synch point
2025-07-02 04:52:32.581 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.581
2025-07-02 04:52:32.581 # do intraline marking on the synch pair
2025-07-02 04:52:32.581 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.581 if eqi is None:
2025-07-02 04:52:32.582 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.582 atags = btags = ""
2025-07-02 04:52:32.582 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.582 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.582 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.582 if tag == 'replace':
2025-07-02 04:52:32.582 atags += '^' * la
2025-07-02 04:52:32.582 btags += '^' * lb
2025-07-02 04:52:32.582 elif tag == 'delete':
2025-07-02 04:52:32.582 atags += '-' * la
2025-07-02 04:52:32.582 elif tag == 'insert':
2025-07-02 04:52:32.582 btags += '+' * lb
2025-07-02 04:52:32.582 elif tag == 'equal':
2025-07-02 04:52:32.582 atags += ' ' * la
2025-07-02 04:52:32.582 btags += ' ' * lb
2025-07-02 04:52:32.582 else:
2025-07-02 04:52:32.582 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.582 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.582 else:
2025-07-02 04:52:32.582 # the synch pair is identical
2025-07-02 04:52:32.583 yield ' ' + aelt
2025-07-02 04:52:32.583
2025-07-02 04:52:32.583 # pump out diffs from after the synch point
2025-07-02 04:52:32.583 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.583
2025-07-02 04:52:32.583 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.583 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.583
2025-07-02 04:52:32.583 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.583 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.583 alo = 252, ahi = 1101
2025-07-02 04:52:32.583 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.583 blo = 252, bhi = 1101
2025-07-02 04:52:32.583
2025-07-02 04:52:32.583 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.583 g = []
2025-07-02 04:52:32.583 if alo < ahi:
2025-07-02 04:52:32.583 if blo < bhi:
2025-07-02 04:52:32.583 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.583 else:
2025-07-02 04:52:32.583 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.584 elif blo < bhi:
2025-07-02 04:52:32.584 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.584
2025-07-02 04:52:32.584 > yield from g
2025-07-02 04:52:32.584
2025-07-02 04:52:32.584 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.584 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.584
2025-07-02 04:52:32.584 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.584 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.584 alo = 252, ahi = 1101
2025-07-02 04:52:32.584 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.584 blo = 252, bhi = 1101
2025-07-02 04:52:32.584
2025-07-02 04:52:32.584 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.584 r"""
2025-07-02 04:52:32.584 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.584 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.584 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.584 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.585
2025-07-02 04:52:32.585 Example:
2025-07-02 04:52:32.585
2025-07-02 04:52:32.585 >>> d = Differ()
2025-07-02 04:52:32.585 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.585 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.585 >>> print(''.join(results), end="")
2025-07-02 04:52:32.585 - abcDefghiJkl
2025-07-02 04:52:32.585 + abcdefGhijkl
2025-07-02 04:52:32.585 """
2025-07-02 04:52:32.585
2025-07-02 04:52:32.585 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.585 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.585 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.585 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.585 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.585
2025-07-02 04:52:32.585 # search for the pair that matches best without being identical
2025-07-02 04:52:32.585 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.586 # on junk -- unless we have to)
2025-07-02 04:52:32.586 for j in range(blo, bhi):
2025-07-02 04:52:32.586 bj = b[j]
2025-07-02 04:52:32.586 cruncher.set_seq2(bj)
2025-07-02 04:52:32.586 for i in range(alo, ahi):
2025-07-02 04:52:32.586 ai = a[i]
2025-07-02 04:52:32.586 if ai == bj:
2025-07-02 04:52:32.586 if eqi is None:
2025-07-02 04:52:32.586 eqi, eqj = i, j
2025-07-02 04:52:32.586 continue
2025-07-02 04:52:32.586 cruncher.set_seq1(ai)
2025-07-02 04:52:32.586 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.586 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.586 # compares by a factor of 3.
2025-07-02 04:52:32.586 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.586 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.586 # of the computation is cached by cruncher
2025-07-02 04:52:32.586 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.586 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.586 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.586 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.587 if best_ratio < cutoff:
2025-07-02 04:52:32.587 # no non-identical "pretty close" pair
2025-07-02 04:52:32.587 if eqi is None:
2025-07-02 04:52:32.587 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.587 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.587 return
2025-07-02 04:52:32.587 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.587 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.587 else:
2025-07-02 04:52:32.587 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.587 eqi = None
2025-07-02 04:52:32.587
2025-07-02 04:52:32.587 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.587 # identical
2025-07-02 04:52:32.587
2025-07-02 04:52:32.587 # pump out diffs from before the synch point
2025-07-02 04:52:32.587 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.587
2025-07-02 04:52:32.587 # do intraline marking on the synch pair
2025-07-02 04:52:32.587 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.588 if eqi is None:
2025-07-02 04:52:32.588 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.588 atags = btags = ""
2025-07-02 04:52:32.588 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.588 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.588 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.588 if tag == 'replace':
2025-07-02 04:52:32.588 atags += '^' * la
2025-07-02 04:52:32.588 btags += '^' * lb
2025-07-02 04:52:32.588 elif tag == 'delete':
2025-07-02 04:52:32.588 atags += '-' * la
2025-07-02 04:52:32.588 elif tag == 'insert':
2025-07-02 04:52:32.588 btags += '+' * lb
2025-07-02 04:52:32.588 elif tag == 'equal':
2025-07-02 04:52:32.588 atags += ' ' * la
2025-07-02 04:52:32.588 btags += ' ' * lb
2025-07-02 04:52:32.588 else:
2025-07-02 04:52:32.588 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.588 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.588 else:
2025-07-02 04:52:32.588 # the synch pair is identical
2025-07-02 04:52:32.589 yield ' ' + aelt
2025-07-02 04:52:32.589
2025-07-02 04:52:32.589 # pump out diffs from after the synch point
2025-07-02 04:52:32.589 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.589
2025-07-02 04:52:32.589 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.589 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.589
2025-07-02 04:52:32.589 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.589 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.589 alo = 253, ahi = 1101
2025-07-02 04:52:32.589 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.589 blo = 253, bhi = 1101
2025-07-02 04:52:32.589
2025-07-02 04:52:32.589 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.589 g = []
2025-07-02 04:52:32.589 if alo < ahi:
2025-07-02 04:52:32.589 if blo < bhi:
2025-07-02 04:52:32.589 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.589 else:
2025-07-02 04:52:32.590 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.590 elif blo < bhi:
2025-07-02 04:52:32.590 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.590
2025-07-02 04:52:32.590 > yield from g
2025-07-02 04:52:32.590
2025-07-02 04:52:32.590 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.590 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.590
2025-07-02 04:52:32.590 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.590 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.590 alo = 253, ahi = 1101
2025-07-02 04:52:32.590 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.590 blo = 253, bhi = 1101
2025-07-02 04:52:32.590
2025-07-02 04:52:32.590 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.590 r"""
2025-07-02 04:52:32.590 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.590 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.590 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.591 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.591
2025-07-02 04:52:32.591 Example:
2025-07-02 04:52:32.591
2025-07-02 04:52:32.591 >>> d = Differ()
2025-07-02 04:52:32.591 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.591 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.591 >>> print(''.join(results), end="")
2025-07-02 04:52:32.591 - abcDefghiJkl
2025-07-02 04:52:32.591 + abcdefGhijkl
2025-07-02 04:52:32.591 """
2025-07-02 04:52:32.591
2025-07-02 04:52:32.591 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.591 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.591 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.591 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.591 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.591
2025-07-02 04:52:32.591 # search for the pair that matches best without being identical
2025-07-02 04:52:32.592 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.592 # on junk -- unless we have to)
2025-07-02 04:52:32.592 for j in range(blo, bhi):
2025-07-02 04:52:32.592 bj = b[j]
2025-07-02 04:52:32.592 cruncher.set_seq2(bj)
2025-07-02 04:52:32.592 for i in range(alo, ahi):
2025-07-02 04:52:32.592 ai = a[i]
2025-07-02 04:52:32.592 if ai == bj:
2025-07-02 04:52:32.592 if eqi is None:
2025-07-02 04:52:32.592 eqi, eqj = i, j
2025-07-02 04:52:32.592 continue
2025-07-02 04:52:32.592 cruncher.set_seq1(ai)
2025-07-02 04:52:32.592 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.592 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.592 # compares by a factor of 3.
2025-07-02 04:52:32.592 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.592 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.592 # of the computation is cached by cruncher
2025-07-02 04:52:32.592 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.592 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.592 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.593 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.593 if best_ratio < cutoff:
2025-07-02 04:52:32.593 # no non-identical "pretty close" pair
2025-07-02 04:52:32.593 if eqi is None:
2025-07-02 04:52:32.593 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.593 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.593 return
2025-07-02 04:52:32.593 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.593 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.593 else:
2025-07-02 04:52:32.593 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.593 eqi = None
2025-07-02 04:52:32.593
2025-07-02 04:52:32.593 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.593 # identical
2025-07-02 04:52:32.593
2025-07-02 04:52:32.593 # pump out diffs from before the synch point
2025-07-02 04:52:32.593 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.593
2025-07-02 04:52:32.593 # do intraline marking on the synch pair
2025-07-02 04:52:32.594 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.594 if eqi is None:
2025-07-02 04:52:32.594 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.594 atags = btags = ""
2025-07-02 04:52:32.594 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.594 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.594 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.594 if tag == 'replace':
2025-07-02 04:52:32.594 atags += '^' * la
2025-07-02 04:52:32.594 btags += '^' * lb
2025-07-02 04:52:32.594 elif tag == 'delete':
2025-07-02 04:52:32.594 atags += '-' * la
2025-07-02 04:52:32.594 elif tag == 'insert':
2025-07-02 04:52:32.594 btags += '+' * lb
2025-07-02 04:52:32.594 elif tag == 'equal':
2025-07-02 04:52:32.594 atags += ' ' * la
2025-07-02 04:52:32.594 btags += ' ' * lb
2025-07-02 04:52:32.594 else:
2025-07-02 04:52:32.594 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.594 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.595 else:
2025-07-02 04:52:32.595 # the synch pair is identical
2025-07-02 04:52:32.595 yield ' ' + aelt
2025-07-02 04:52:32.595
2025-07-02 04:52:32.595 # pump out diffs from after the synch point
2025-07-02 04:52:32.595 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.595
2025-07-02 04:52:32.595 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.595 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.595
2025-07-02 04:52:32.595 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.595 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.595 alo = 254, ahi = 1101
2025-07-02 04:52:32.595 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.595 blo = 254, bhi = 1101
2025-07-02 04:52:32.595
2025-07-02 04:52:32.595 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.595 g = []
2025-07-02 04:52:32.595 if alo < ahi:
2025-07-02 04:52:32.595 if blo < bhi:
2025-07-02 04:52:32.595 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.596 else:
2025-07-02 04:52:32.596 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.596 elif blo < bhi:
2025-07-02 04:52:32.596 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.596
2025-07-02 04:52:32.596 > yield from g
2025-07-02 04:52:32.596
2025-07-02 04:52:32.596 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.596 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.596
2025-07-02 04:52:32.596 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.596 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.596 alo = 254, ahi = 1101
2025-07-02 04:52:32.596 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.596 blo = 254, bhi = 1101
2025-07-02 04:52:32.596
2025-07-02 04:52:32.596 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.596 r"""
2025-07-02 04:52:32.596 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.596 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.597 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.597 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.597
2025-07-02 04:52:32.597 Example:
2025-07-02 04:52:32.597
2025-07-02 04:52:32.597 >>> d = Differ()
2025-07-02 04:52:32.597 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.597 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.597 >>> print(''.join(results), end="")
2025-07-02 04:52:32.597 - abcDefghiJkl
2025-07-02 04:52:32.597 + abcdefGhijkl
2025-07-02 04:52:32.597 """
2025-07-02 04:52:32.597
2025-07-02 04:52:32.597 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.597 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.597 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.597 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.597 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.597
2025-07-02 04:52:32.598 # search for the pair that matches best without being identical
2025-07-02 04:52:32.598 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.598 # on junk -- unless we have to)
2025-07-02 04:52:32.598 for j in range(blo, bhi):
2025-07-02 04:52:32.598 bj = b[j]
2025-07-02 04:52:32.598 cruncher.set_seq2(bj)
2025-07-02 04:52:32.598 for i in range(alo, ahi):
2025-07-02 04:52:32.598 ai = a[i]
2025-07-02 04:52:32.598 if ai == bj:
2025-07-02 04:52:32.598 if eqi is None:
2025-07-02 04:52:32.598 eqi, eqj = i, j
2025-07-02 04:52:32.598 continue
2025-07-02 04:52:32.598 cruncher.set_seq1(ai)
2025-07-02 04:52:32.598 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.598 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.598 # compares by a factor of 3.
2025-07-02 04:52:32.598 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.598 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.598 # of the computation is cached by cruncher
2025-07-02 04:52:32.598 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.599 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.599 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.599 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.599 if best_ratio < cutoff:
2025-07-02 04:52:32.599 # no non-identical "pretty close" pair
2025-07-02 04:52:32.599 if eqi is None:
2025-07-02 04:52:32.599 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.599 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.599 return
2025-07-02 04:52:32.599 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.599 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.599 else:
2025-07-02 04:52:32.599 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.599 eqi = None
2025-07-02 04:52:32.599
2025-07-02 04:52:32.599 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.599 # identical
2025-07-02 04:52:32.599
2025-07-02 04:52:32.599 # pump out diffs from before the synch point
2025-07-02 04:52:32.599 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.600
2025-07-02 04:52:32.600 # do intraline marking on the synch pair
2025-07-02 04:52:32.600 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.600 if eqi is None:
2025-07-02 04:52:32.600 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.600 atags = btags = ""
2025-07-02 04:52:32.600 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.600 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.600 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.600 if tag == 'replace':
2025-07-02 04:52:32.600 atags += '^' * la
2025-07-02 04:52:32.600 btags += '^' * lb
2025-07-02 04:52:32.600 elif tag == 'delete':
2025-07-02 04:52:32.600 atags += '-' * la
2025-07-02 04:52:32.600 elif tag == 'insert':
2025-07-02 04:52:32.600 btags += '+' * lb
2025-07-02 04:52:32.600 elif tag == 'equal':
2025-07-02 04:52:32.600 atags += ' ' * la
2025-07-02 04:52:32.600 btags += ' ' * lb
2025-07-02 04:52:32.600 else:
2025-07-02 04:52:32.600 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.601 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.601 else:
2025-07-02 04:52:32.601 # the synch pair is identical
2025-07-02 04:52:32.601 yield ' ' + aelt
2025-07-02 04:52:32.601
2025-07-02 04:52:32.601 # pump out diffs from after the synch point
2025-07-02 04:52:32.601 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.601
2025-07-02 04:52:32.601 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.601 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.601
2025-07-02 04:52:32.601 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.601 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.601 alo = 255, ahi = 1101
2025-07-02 04:52:32.601 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.601 blo = 255, bhi = 1101
2025-07-02 04:52:32.601
2025-07-02 04:52:32.601 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.601 g = []
2025-07-02 04:52:32.601 if alo < ahi:
2025-07-02 04:52:32.601 if blo < bhi:
2025-07-02 04:52:32.602 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.602 else:
2025-07-02 04:52:32.602 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.602 elif blo < bhi:
2025-07-02 04:52:32.602 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.602
2025-07-02 04:52:32.602 > yield from g
2025-07-02 04:52:32.602
2025-07-02 04:52:32.602 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.602 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.602
2025-07-02 04:52:32.602 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.602 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.602 alo = 255, ahi = 1101
2025-07-02 04:52:32.602 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.602 blo = 255, bhi = 1101
2025-07-02 04:52:32.602
2025-07-02 04:52:32.602 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.602 r"""
2025-07-02 04:52:32.602 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.603 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.603 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.603 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.603
2025-07-02 04:52:32.603 Example:
2025-07-02 04:52:32.603
2025-07-02 04:52:32.603 >>> d = Differ()
2025-07-02 04:52:32.603 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.603 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.603 >>> print(''.join(results), end="")
2025-07-02 04:52:32.603 - abcDefghiJkl
2025-07-02 04:52:32.603 + abcdefGhijkl
2025-07-02 04:52:32.603 """
2025-07-02 04:52:32.603
2025-07-02 04:52:32.603 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.603 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.603 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.603 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.603 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.604
2025-07-02 04:52:32.604 # search for the pair that matches best without being identical
2025-07-02 04:52:32.604 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.604 # on junk -- unless we have to)
2025-07-02 04:52:32.604 for j in range(blo, bhi):
2025-07-02 04:52:32.604 bj = b[j]
2025-07-02 04:52:32.604 cruncher.set_seq2(bj)
2025-07-02 04:52:32.604 for i in range(alo, ahi):
2025-07-02 04:52:32.604 ai = a[i]
2025-07-02 04:52:32.604 if ai == bj:
2025-07-02 04:52:32.604 if eqi is None:
2025-07-02 04:52:32.604 eqi, eqj = i, j
2025-07-02 04:52:32.604 continue
2025-07-02 04:52:32.604 cruncher.set_seq1(ai)
2025-07-02 04:52:32.604 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.604 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.604 # compares by a factor of 3.
2025-07-02 04:52:32.604 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.604 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.604 # of the computation is cached by cruncher
2025-07-02 04:52:32.605 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.605 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.605 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.605 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.605 if best_ratio < cutoff:
2025-07-02 04:52:32.605 # no non-identical "pretty close" pair
2025-07-02 04:52:32.605 if eqi is None:
2025-07-02 04:52:32.605 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.605 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.605 return
2025-07-02 04:52:32.605 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.605 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.605 else:
2025-07-02 04:52:32.605 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.605 eqi = None
2025-07-02 04:52:32.605
2025-07-02 04:52:32.605 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.605 # identical
2025-07-02 04:52:32.605
2025-07-02 04:52:32.605 # pump out diffs from before the synch point
2025-07-02 04:52:32.605 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.606
2025-07-02 04:52:32.606 # do intraline marking on the synch pair
2025-07-02 04:52:32.606 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.606 if eqi is None:
2025-07-02 04:52:32.606 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.606 atags = btags = ""
2025-07-02 04:52:32.606 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.606 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.606 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.606 if tag == 'replace':
2025-07-02 04:52:32.606 atags += '^' * la
2025-07-02 04:52:32.606 btags += '^' * lb
2025-07-02 04:52:32.606 elif tag == 'delete':
2025-07-02 04:52:32.606 atags += '-' * la
2025-07-02 04:52:32.606 elif tag == 'insert':
2025-07-02 04:52:32.606 btags += '+' * lb
2025-07-02 04:52:32.606 elif tag == 'equal':
2025-07-02 04:52:32.606 atags += ' ' * la
2025-07-02 04:52:32.606 btags += ' ' * lb
2025-07-02 04:52:32.606 else:
2025-07-02 04:52:32.606 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.607 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.607 else:
2025-07-02 04:52:32.607 # the synch pair is identical
2025-07-02 04:52:32.607 yield ' ' + aelt
2025-07-02 04:52:32.607
2025-07-02 04:52:32.607 # pump out diffs from after the synch point
2025-07-02 04:52:32.607 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.607
2025-07-02 04:52:32.607 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.607 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.607
2025-07-02 04:52:32.607 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.607 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.607 alo = 256, ahi = 1101
2025-07-02 04:52:32.607 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.607 blo = 256, bhi = 1101
2025-07-02 04:52:32.607
2025-07-02 04:52:32.607 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.607 g = []
2025-07-02 04:52:32.607 if alo < ahi:
2025-07-02 04:52:32.608 if blo < bhi:
2025-07-02 04:52:32.608 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.608 else:
2025-07-02 04:52:32.608 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.608 elif blo < bhi:
2025-07-02 04:52:32.608 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.608
2025-07-02 04:52:32.608 > yield from g
2025-07-02 04:52:32.608
2025-07-02 04:52:32.608 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.608 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.608
2025-07-02 04:52:32.608 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.608 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.608 alo = 256, ahi = 1101
2025-07-02 04:52:32.608 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.608 blo = 256, bhi = 1101
2025-07-02 04:52:32.608
2025-07-02 04:52:32.608 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.608 r"""
2025-07-02 04:52:32.608 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.609 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.609 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.609 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.609
2025-07-02 04:52:32.609 Example:
2025-07-02 04:52:32.609
2025-07-02 04:52:32.609 >>> d = Differ()
2025-07-02 04:52:32.609 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.609 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.609 >>> print(''.join(results), end="")
2025-07-02 04:52:32.609 - abcDefghiJkl
2025-07-02 04:52:32.609 + abcdefGhijkl
2025-07-02 04:52:32.609 """
2025-07-02 04:52:32.609
2025-07-02 04:52:32.609 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.609 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.609 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.609 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.610 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.610
2025-07-02 04:52:32.610 # search for the pair that matches best without being identical
2025-07-02 04:52:32.610 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.610 # on junk -- unless we have to)
2025-07-02 04:52:32.610 for j in range(blo, bhi):
2025-07-02 04:52:32.610 bj = b[j]
2025-07-02 04:52:32.610 cruncher.set_seq2(bj)
2025-07-02 04:52:32.610 for i in range(alo, ahi):
2025-07-02 04:52:32.610 ai = a[i]
2025-07-02 04:52:32.610 if ai == bj:
2025-07-02 04:52:32.610 if eqi is None:
2025-07-02 04:52:32.610 eqi, eqj = i, j
2025-07-02 04:52:32.610 continue
2025-07-02 04:52:32.610 cruncher.set_seq1(ai)
2025-07-02 04:52:32.610 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.610 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.610 # compares by a factor of 3.
2025-07-02 04:52:32.610 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.610 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.610 # of the computation is cached by cruncher
2025-07-02 04:52:32.611 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.611 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.611 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.611 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.611 if best_ratio < cutoff:
2025-07-02 04:52:32.611 # no non-identical "pretty close" pair
2025-07-02 04:52:32.611 if eqi is None:
2025-07-02 04:52:32.611 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.611 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.611 return
2025-07-02 04:52:32.611 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.611 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.611 else:
2025-07-02 04:52:32.611 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.611 eqi = None
2025-07-02 04:52:32.611
2025-07-02 04:52:32.611 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.611 # identical
2025-07-02 04:52:32.611
2025-07-02 04:52:32.611 # pump out diffs from before the synch point
2025-07-02 04:52:32.611 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.612
2025-07-02 04:52:32.612 # do intraline marking on the synch pair
2025-07-02 04:52:32.612 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.612 if eqi is None:
2025-07-02 04:52:32.612 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.612 atags = btags = ""
2025-07-02 04:52:32.612 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.612 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.612 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.612 if tag == 'replace':
2025-07-02 04:52:32.612 atags += '^' * la
2025-07-02 04:52:32.612 btags += '^' * lb
2025-07-02 04:52:32.612 elif tag == 'delete':
2025-07-02 04:52:32.612 atags += '-' * la
2025-07-02 04:52:32.612 elif tag == 'insert':
2025-07-02 04:52:32.612 btags += '+' * lb
2025-07-02 04:52:32.612 elif tag == 'equal':
2025-07-02 04:52:32.612 atags += ' ' * la
2025-07-02 04:52:32.612 btags += ' ' * lb
2025-07-02 04:52:32.613 else:
2025-07-02 04:52:32.613 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.613 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.613 else:
2025-07-02 04:52:32.613 # the synch pair is identical
2025-07-02 04:52:32.613 yield ' ' + aelt
2025-07-02 04:52:32.613
2025-07-02 04:52:32.613 # pump out diffs from after the synch point
2025-07-02 04:52:32.613 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.613
2025-07-02 04:52:32.613 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.613 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.613
2025-07-02 04:52:32.613 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.613 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.613 alo = 257, ahi = 1101
2025-07-02 04:52:32.613 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.613 blo = 257, bhi = 1101
2025-07-02 04:52:32.613
2025-07-02 04:52:32.613 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.614 g = []
2025-07-02 04:52:32.614 if alo < ahi:
2025-07-02 04:52:32.614 if blo < bhi:
2025-07-02 04:52:32.614 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.614 else:
2025-07-02 04:52:32.614 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.614 elif blo < bhi:
2025-07-02 04:52:32.614 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.614
2025-07-02 04:52:32.614 > yield from g
2025-07-02 04:52:32.614
2025-07-02 04:52:32.614 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.614 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.614
2025-07-02 04:52:32.614 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.614 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.614 alo = 257, ahi = 1101
2025-07-02 04:52:32.614 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.614 blo = 257, bhi = 1101
2025-07-02 04:52:32.614
2025-07-02 04:52:32.615 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.615 r"""
2025-07-02 04:52:32.615 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.615 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.615 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.615 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.615
2025-07-02 04:52:32.615 Example:
2025-07-02 04:52:32.615
2025-07-02 04:52:32.615 >>> d = Differ()
2025-07-02 04:52:32.615 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.615 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.615 >>> print(''.join(results), end="")
2025-07-02 04:52:32.615 - abcDefghiJkl
2025-07-02 04:52:32.615 + abcdefGhijkl
2025-07-02 04:52:32.615 """
2025-07-02 04:52:32.615
2025-07-02 04:52:32.616 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.616 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.616 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.616 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.616 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.616
2025-07-02 04:52:32.616 # search for the pair that matches best without being identical
2025-07-02 04:52:32.616 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.616 # on junk -- unless we have to)
2025-07-02 04:52:32.616 for j in range(blo, bhi):
2025-07-02 04:52:32.616 bj = b[j]
2025-07-02 04:52:32.616 cruncher.set_seq2(bj)
2025-07-02 04:52:32.616 for i in range(alo, ahi):
2025-07-02 04:52:32.616 ai = a[i]
2025-07-02 04:52:32.616 if ai == bj:
2025-07-02 04:52:32.616 if eqi is None:
2025-07-02 04:52:32.616 eqi, eqj = i, j
2025-07-02 04:52:32.616 continue
2025-07-02 04:52:32.616 cruncher.set_seq1(ai)
2025-07-02 04:52:32.616 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.616 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.617 # compares by a factor of 3.
2025-07-02 04:52:32.617 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.617 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.617 # of the computation is cached by cruncher
2025-07-02 04:52:32.617 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.617 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.617 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.617 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.617 if best_ratio < cutoff:
2025-07-02 04:52:32.617 # no non-identical "pretty close" pair
2025-07-02 04:52:32.617 if eqi is None:
2025-07-02 04:52:32.617 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.617 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.617 return
2025-07-02 04:52:32.617 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.617 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.617 else:
2025-07-02 04:52:32.617 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.617 eqi = None
2025-07-02 04:52:32.617
2025-07-02 04:52:32.617 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.618 # identical
2025-07-02 04:52:32.618
2025-07-02 04:52:32.618 # pump out diffs from before the synch point
2025-07-02 04:52:32.618 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.618
2025-07-02 04:52:32.618 # do intraline marking on the synch pair
2025-07-02 04:52:32.618 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.618 if eqi is None:
2025-07-02 04:52:32.618 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.618 atags = btags = ""
2025-07-02 04:52:32.618 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.618 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.618 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.618 if tag == 'replace':
2025-07-02 04:52:32.618 atags += '^' * la
2025-07-02 04:52:32.618 btags += '^' * lb
2025-07-02 04:52:32.618 elif tag == 'delete':
2025-07-02 04:52:32.618 atags += '-' * la
2025-07-02 04:52:32.618 elif tag == 'insert':
2025-07-02 04:52:32.618 btags += '+' * lb
2025-07-02 04:52:32.618 elif tag == 'equal':
2025-07-02 04:52:32.619 atags += ' ' * la
2025-07-02 04:52:32.619 btags += ' ' * lb
2025-07-02 04:52:32.619 else:
2025-07-02 04:52:32.619 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.619 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.619 else:
2025-07-02 04:52:32.619 # the synch pair is identical
2025-07-02 04:52:32.619 yield ' ' + aelt
2025-07-02 04:52:32.619
2025-07-02 04:52:32.619 # pump out diffs from after the synch point
2025-07-02 04:52:32.619 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.619
2025-07-02 04:52:32.619 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.619 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.619
2025-07-02 04:52:32.619 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.619 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.619 alo = 258, ahi = 1101
2025-07-02 04:52:32.619 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.619 blo = 258, bhi = 1101
2025-07-02 04:52:32.619
2025-07-02 04:52:32.620 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.620 g = []
2025-07-02 04:52:32.620 if alo < ahi:
2025-07-02 04:52:32.620 if blo < bhi:
2025-07-02 04:52:32.620 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.620 else:
2025-07-02 04:52:32.620 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.620 elif blo < bhi:
2025-07-02 04:52:32.620 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.620
2025-07-02 04:52:32.620 > yield from g
2025-07-02 04:52:32.620
2025-07-02 04:52:32.620 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.620 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.620
2025-07-02 04:52:32.620 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.620 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.620 alo = 258, ahi = 1101
2025-07-02 04:52:32.620 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.620 blo = 258, bhi = 1101
2025-07-02 04:52:32.620
2025-07-02 04:52:32.621 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.621 r"""
2025-07-02 04:52:32.621 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.621 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.621 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.621 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.621
2025-07-02 04:52:32.621 Example:
2025-07-02 04:52:32.621
2025-07-02 04:52:32.621 >>> d = Differ()
2025-07-02 04:52:32.621 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.621 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.621 >>> print(''.join(results), end="")
2025-07-02 04:52:32.621 - abcDefghiJkl
2025-07-02 04:52:32.621 + abcdefGhijkl
2025-07-02 04:52:32.621 """
2025-07-02 04:52:32.621
2025-07-02 04:52:32.621 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.621 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.621 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.622 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.622 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.622
2025-07-02 04:52:32.622 # search for the pair that matches best without being identical
2025-07-02 04:52:32.622 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.622 # on junk -- unless we have to)
2025-07-02 04:52:32.622 for j in range(blo, bhi):
2025-07-02 04:52:32.622 bj = b[j]
2025-07-02 04:52:32.622 cruncher.set_seq2(bj)
2025-07-02 04:52:32.622 for i in range(alo, ahi):
2025-07-02 04:52:32.622 ai = a[i]
2025-07-02 04:52:32.622 if ai == bj:
2025-07-02 04:52:32.622 if eqi is None:
2025-07-02 04:52:32.622 eqi, eqj = i, j
2025-07-02 04:52:32.622 continue
2025-07-02 04:52:32.622 cruncher.set_seq1(ai)
2025-07-02 04:52:32.622 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.622 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.622 # compares by a factor of 3.
2025-07-02 04:52:32.622 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.622 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.622 # of the computation is cached by cruncher
2025-07-02 04:52:32.623 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.623 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.623 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.623 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.623 if best_ratio < cutoff:
2025-07-02 04:52:32.623 # no non-identical "pretty close" pair
2025-07-02 04:52:32.623 if eqi is None:
2025-07-02 04:52:32.623 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.623 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.623 return
2025-07-02 04:52:32.623 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.623 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.623 else:
2025-07-02 04:52:32.623 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.623 eqi = None
2025-07-02 04:52:32.623
2025-07-02 04:52:32.623 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.623 # identical
2025-07-02 04:52:32.623
2025-07-02 04:52:32.624 # pump out diffs from before the synch point
2025-07-02 04:52:32.624 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.624
2025-07-02 04:52:32.624 # do intraline marking on the synch pair
2025-07-02 04:52:32.624 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.624 if eqi is None:
2025-07-02 04:52:32.624 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.624 atags = btags = ""
2025-07-02 04:52:32.624 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.624 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.624 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.624 if tag == 'replace':
2025-07-02 04:52:32.624 atags += '^' * la
2025-07-02 04:52:32.624 btags += '^' * lb
2025-07-02 04:52:32.624 elif tag == 'delete':
2025-07-02 04:52:32.624 atags += '-' * la
2025-07-02 04:52:32.624 elif tag == 'insert':
2025-07-02 04:52:32.624 btags += '+' * lb
2025-07-02 04:52:32.624 elif tag == 'equal':
2025-07-02 04:52:32.624 atags += ' ' * la
2025-07-02 04:52:32.625 btags += ' ' * lb
2025-07-02 04:52:32.625 else:
2025-07-02 04:52:32.625 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.625 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.625 else:
2025-07-02 04:52:32.625 # the synch pair is identical
2025-07-02 04:52:32.625 yield ' ' + aelt
2025-07-02 04:52:32.625
2025-07-02 04:52:32.625 # pump out diffs from after the synch point
2025-07-02 04:52:32.625 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.625
2025-07-02 04:52:32.625 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.625 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.625
2025-07-02 04:52:32.625 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.625 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.625 alo = 259, ahi = 1101
2025-07-02 04:52:32.625 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.625 blo = 259, bhi = 1101
2025-07-02 04:52:32.625
2025-07-02 04:52:32.625 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.626 g = []
2025-07-02 04:52:32.626 if alo < ahi:
2025-07-02 04:52:32.626 if blo < bhi:
2025-07-02 04:52:32.626 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.626 else:
2025-07-02 04:52:32.626 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.626 elif blo < bhi:
2025-07-02 04:52:32.626 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.626
2025-07-02 04:52:32.626 > yield from g
2025-07-02 04:52:32.626
2025-07-02 04:52:32.626 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.626 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.626
2025-07-02 04:52:32.626 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.626 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.626 alo = 259, ahi = 1101
2025-07-02 04:52:32.626 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.626 blo = 259, bhi = 1101
2025-07-02 04:52:32.626
2025-07-02 04:52:32.626 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.627 r"""
2025-07-02 04:52:32.627 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.627 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.627 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.627 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.627
2025-07-02 04:52:32.627 Example:
2025-07-02 04:52:32.627
2025-07-02 04:52:32.627 >>> d = Differ()
2025-07-02 04:52:32.627 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.627 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.627 >>> print(''.join(results), end="")
2025-07-02 04:52:32.627 - abcDefghiJkl
2025-07-02 04:52:32.627 + abcdefGhijkl
2025-07-02 04:52:32.627 """
2025-07-02 04:52:32.627
2025-07-02 04:52:32.627 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.627 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.627 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.627 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.628 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.628
2025-07-02 04:52:32.628 # search for the pair that matches best without being identical
2025-07-02 04:52:32.628 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.628 # on junk -- unless we have to)
2025-07-02 04:52:32.628 for j in range(blo, bhi):
2025-07-02 04:52:32.628 bj = b[j]
2025-07-02 04:52:32.628 cruncher.set_seq2(bj)
2025-07-02 04:52:32.628 for i in range(alo, ahi):
2025-07-02 04:52:32.628 ai = a[i]
2025-07-02 04:52:32.628 if ai == bj:
2025-07-02 04:52:32.628 if eqi is None:
2025-07-02 04:52:32.628 eqi, eqj = i, j
2025-07-02 04:52:32.628 continue
2025-07-02 04:52:32.628 cruncher.set_seq1(ai)
2025-07-02 04:52:32.628 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.628 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.628 # compares by a factor of 3.
2025-07-02 04:52:32.628 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.628 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.628 # of the computation is cached by cruncher
2025-07-02 04:52:32.628 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.629 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.629 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.629 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.629 if best_ratio < cutoff:
2025-07-02 04:52:32.629 # no non-identical "pretty close" pair
2025-07-02 04:52:32.629 if eqi is None:
2025-07-02 04:52:32.629 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.629 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.629 return
2025-07-02 04:52:32.629 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.629 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.629 else:
2025-07-02 04:52:32.629 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.629 eqi = None
2025-07-02 04:52:32.629
2025-07-02 04:52:32.629 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.629 # identical
2025-07-02 04:52:32.629
2025-07-02 04:52:32.629 # pump out diffs from before the synch point
2025-07-02 04:52:32.629 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.629
2025-07-02 04:52:32.630 # do intraline marking on the synch pair
2025-07-02 04:52:32.630 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.630 if eqi is None:
2025-07-02 04:52:32.630 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.630 atags = btags = ""
2025-07-02 04:52:32.630 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.630 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.630 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.630 if tag == 'replace':
2025-07-02 04:52:32.630 atags += '^' * la
2025-07-02 04:52:32.630 btags += '^' * lb
2025-07-02 04:52:32.630 elif tag == 'delete':
2025-07-02 04:52:32.630 atags += '-' * la
2025-07-02 04:52:32.630 elif tag == 'insert':
2025-07-02 04:52:32.630 btags += '+' * lb
2025-07-02 04:52:32.630 elif tag == 'equal':
2025-07-02 04:52:32.630 atags += ' ' * la
2025-07-02 04:52:32.630 btags += ' ' * lb
2025-07-02 04:52:32.630 else:
2025-07-02 04:52:32.630 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.630 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.630 else:
2025-07-02 04:52:32.631 # the synch pair is identical
2025-07-02 04:52:32.631 yield ' ' + aelt
2025-07-02 04:52:32.631
2025-07-02 04:52:32.631 # pump out diffs from after the synch point
2025-07-02 04:52:32.631 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.631
2025-07-02 04:52:32.631 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.631 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.631
2025-07-02 04:52:32.631 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.631 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.631 alo = 260, ahi = 1101
2025-07-02 04:52:32.631 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.631 blo = 260, bhi = 1101
2025-07-02 04:52:32.631
2025-07-02 04:52:32.631 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.631 g = []
2025-07-02 04:52:32.631 if alo < ahi:
2025-07-02 04:52:32.631 if blo < bhi:
2025-07-02 04:52:32.632 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.632 else:
2025-07-02 04:52:32.632 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.632 elif blo < bhi:
2025-07-02 04:52:32.632 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.632
2025-07-02 04:52:32.632 > yield from g
2025-07-02 04:52:32.632
2025-07-02 04:52:32.632 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.632 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.632
2025-07-02 04:52:32.632 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.632 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.632 alo = 260, ahi = 1101
2025-07-02 04:52:32.632 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.632 blo = 260, bhi = 1101
2025-07-02 04:52:32.632
2025-07-02 04:52:32.632 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.632 r"""
2025-07-02 04:52:32.632 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.632 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.633 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.633 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.633
2025-07-02 04:52:32.633 Example:
2025-07-02 04:52:32.633
2025-07-02 04:52:32.633 >>> d = Differ()
2025-07-02 04:52:32.633 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.633 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.633 >>> print(''.join(results), end="")
2025-07-02 04:52:32.633 - abcDefghiJkl
2025-07-02 04:52:32.633 + abcdefGhijkl
2025-07-02 04:52:32.633 """
2025-07-02 04:52:32.633
2025-07-02 04:52:32.633 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.633 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.633 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.633 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.633 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.634
2025-07-02 04:52:32.634 # search for the pair that matches best without being identical
2025-07-02 04:52:32.634 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.634 # on junk -- unless we have to)
2025-07-02 04:52:32.634 for j in range(blo, bhi):
2025-07-02 04:52:32.634 bj = b[j]
2025-07-02 04:52:32.634 cruncher.set_seq2(bj)
2025-07-02 04:52:32.634 for i in range(alo, ahi):
2025-07-02 04:52:32.634 ai = a[i]
2025-07-02 04:52:32.634 if ai == bj:
2025-07-02 04:52:32.634 if eqi is None:
2025-07-02 04:52:32.634 eqi, eqj = i, j
2025-07-02 04:52:32.634 continue
2025-07-02 04:52:32.634 cruncher.set_seq1(ai)
2025-07-02 04:52:32.634 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.634 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.634 # compares by a factor of 3.
2025-07-02 04:52:32.634 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.634 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.634 # of the computation is cached by cruncher
2025-07-02 04:52:32.634 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.635 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.635 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.635 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.635 if best_ratio < cutoff:
2025-07-02 04:52:32.635 # no non-identical "pretty close" pair
2025-07-02 04:52:32.635 if eqi is None:
2025-07-02 04:52:32.635 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.635 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.635 return
2025-07-02 04:52:32.635 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.635 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.635 else:
2025-07-02 04:52:32.635 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.635 eqi = None
2025-07-02 04:52:32.635
2025-07-02 04:52:32.635 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.635 # identical
2025-07-02 04:52:32.635
2025-07-02 04:52:32.635 # pump out diffs from before the synch point
2025-07-02 04:52:32.635 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.635
2025-07-02 04:52:32.636 # do intraline marking on the synch pair
2025-07-02 04:52:32.636 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.636 if eqi is None:
2025-07-02 04:52:32.636 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.636 atags = btags = ""
2025-07-02 04:52:32.636 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.636 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.636 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.636 if tag == 'replace':
2025-07-02 04:52:32.636 atags += '^' * la
2025-07-02 04:52:32.636 btags += '^' * lb
2025-07-02 04:52:32.636 elif tag == 'delete':
2025-07-02 04:52:32.636 atags += '-' * la
2025-07-02 04:52:32.636 elif tag == 'insert':
2025-07-02 04:52:32.636 btags += '+' * lb
2025-07-02 04:52:32.636 elif tag == 'equal':
2025-07-02 04:52:32.636 atags += ' ' * la
2025-07-02 04:52:32.636 btags += ' ' * lb
2025-07-02 04:52:32.636 else:
2025-07-02 04:52:32.636 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.637 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.637 else:
2025-07-02 04:52:32.637 # the synch pair is identical
2025-07-02 04:52:32.637 yield ' ' + aelt
2025-07-02 04:52:32.637
2025-07-02 04:52:32.637 # pump out diffs from after the synch point
2025-07-02 04:52:32.637 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.637
2025-07-02 04:52:32.637 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.637 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.637
2025-07-02 04:52:32.637 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.637 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.637 alo = 261, ahi = 1101
2025-07-02 04:52:32.637 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.637 blo = 261, bhi = 1101
2025-07-02 04:52:32.637
2025-07-02 04:52:32.637 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.637 g = []
2025-07-02 04:52:32.637 if alo < ahi:
2025-07-02 04:52:32.637 if blo < bhi:
2025-07-02 04:52:32.638 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.638 else:
2025-07-02 04:52:32.638 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.638 elif blo < bhi:
2025-07-02 04:52:32.638 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.638
2025-07-02 04:52:32.638 > yield from g
2025-07-02 04:52:32.638
2025-07-02 04:52:32.638 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.638 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.638
2025-07-02 04:52:32.638 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.638 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.638 alo = 261, ahi = 1101
2025-07-02 04:52:32.638 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.638 blo = 261, bhi = 1101
2025-07-02 04:52:32.638
2025-07-02 04:52:32.638 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.638 r"""
2025-07-02 04:52:32.638 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.638 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.639 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.639 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.639
2025-07-02 04:52:32.639 Example:
2025-07-02 04:52:32.639
2025-07-02 04:52:32.639 >>> d = Differ()
2025-07-02 04:52:32.639 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.639 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.639 >>> print(''.join(results), end="")
2025-07-02 04:52:32.639 - abcDefghiJkl
2025-07-02 04:52:32.639 + abcdefGhijkl
2025-07-02 04:52:32.639 """
2025-07-02 04:52:32.639
2025-07-02 04:52:32.639 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.639 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.639 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.639 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.639 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.640
2025-07-02 04:52:32.640 # search for the pair that matches best without being identical
2025-07-02 04:52:32.640 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.640 # on junk -- unless we have to)
2025-07-02 04:52:32.640 for j in range(blo, bhi):
2025-07-02 04:52:32.640 bj = b[j]
2025-07-02 04:52:32.640 cruncher.set_seq2(bj)
2025-07-02 04:52:32.640 for i in range(alo, ahi):
2025-07-02 04:52:32.640 ai = a[i]
2025-07-02 04:52:32.640 if ai == bj:
2025-07-02 04:52:32.640 if eqi is None:
2025-07-02 04:52:32.640 eqi, eqj = i, j
2025-07-02 04:52:32.640 continue
2025-07-02 04:52:32.640 cruncher.set_seq1(ai)
2025-07-02 04:52:32.640 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.640 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.640 # compares by a factor of 3.
2025-07-02 04:52:32.640 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.640 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.641 # of the computation is cached by cruncher
2025-07-02 04:52:32.641 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.641 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.641 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.641 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.641 if best_ratio < cutoff:
2025-07-02 04:52:32.641 # no non-identical "pretty close" pair
2025-07-02 04:52:32.641 if eqi is None:
2025-07-02 04:52:32.641 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.641 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.641 return
2025-07-02 04:52:32.641 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.641 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.641 else:
2025-07-02 04:52:32.641 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.641 eqi = None
2025-07-02 04:52:32.641
2025-07-02 04:52:32.641 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.641 # identical
2025-07-02 04:52:32.641
2025-07-02 04:52:32.641 # pump out diffs from before the synch point
2025-07-02 04:52:32.642 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.642
2025-07-02 04:52:32.642 # do intraline marking on the synch pair
2025-07-02 04:52:32.642 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.642 if eqi is None:
2025-07-02 04:52:32.642 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.642 atags = btags = ""
2025-07-02 04:52:32.642 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.642 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.642 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.642 if tag == 'replace':
2025-07-02 04:52:32.642 atags += '^' * la
2025-07-02 04:52:32.642 btags += '^' * lb
2025-07-02 04:52:32.642 elif tag == 'delete':
2025-07-02 04:52:32.642 atags += '-' * la
2025-07-02 04:52:32.642 elif tag == 'insert':
2025-07-02 04:52:32.642 btags += '+' * lb
2025-07-02 04:52:32.642 elif tag == 'equal':
2025-07-02 04:52:32.642 atags += ' ' * la
2025-07-02 04:52:32.642 btags += ' ' * lb
2025-07-02 04:52:32.642 else:
2025-07-02 04:52:32.643 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.643 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.643 else:
2025-07-02 04:52:32.643 # the synch pair is identical
2025-07-02 04:52:32.643 yield ' ' + aelt
2025-07-02 04:52:32.643
2025-07-02 04:52:32.643 # pump out diffs from after the synch point
2025-07-02 04:52:32.643 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.643
2025-07-02 04:52:32.643 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.643 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.643
2025-07-02 04:52:32.643 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.643 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.643 alo = 262, ahi = 1101
2025-07-02 04:52:32.643 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.643 blo = 262, bhi = 1101
2025-07-02 04:52:32.643
2025-07-02 04:52:32.643 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.643 g = []
2025-07-02 04:52:32.644 if alo < ahi:
2025-07-02 04:52:32.644 if blo < bhi:
2025-07-02 04:52:32.644 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.644 else:
2025-07-02 04:52:32.644 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.644 elif blo < bhi:
2025-07-02 04:52:32.644 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.644
2025-07-02 04:52:32.644 > yield from g
2025-07-02 04:52:32.644
2025-07-02 04:52:32.644 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.644 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.644
2025-07-02 04:52:32.644 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.644 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.644 alo = 262, ahi = 1101
2025-07-02 04:52:32.644 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.644 blo = 262, bhi = 1101
2025-07-02 04:52:32.644
2025-07-02 04:52:32.644 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.644 r"""
2025-07-02 04:52:32.645 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.645 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.645 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.645 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.645
2025-07-02 04:52:32.645 Example:
2025-07-02 04:52:32.645
2025-07-02 04:52:32.645 >>> d = Differ()
2025-07-02 04:52:32.645 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.645 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.645 >>> print(''.join(results), end="")
2025-07-02 04:52:32.645 - abcDefghiJkl
2025-07-02 04:52:32.645 + abcdefGhijkl
2025-07-02 04:52:32.645 """
2025-07-02 04:52:32.645
2025-07-02 04:52:32.645 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.645 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.645 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.646 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.646 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.646
2025-07-02 04:52:32.646 # search for the pair that matches best without being identical
2025-07-02 04:52:32.646 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.646 # on junk -- unless we have to)
2025-07-02 04:52:32.646 for j in range(blo, bhi):
2025-07-02 04:52:32.646 bj = b[j]
2025-07-02 04:52:32.646 cruncher.set_seq2(bj)
2025-07-02 04:52:32.646 for i in range(alo, ahi):
2025-07-02 04:52:32.646 ai = a[i]
2025-07-02 04:52:32.646 if ai == bj:
2025-07-02 04:52:32.646 if eqi is None:
2025-07-02 04:52:32.646 eqi, eqj = i, j
2025-07-02 04:52:32.646 continue
2025-07-02 04:52:32.646 cruncher.set_seq1(ai)
2025-07-02 04:52:32.646 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.646 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.646 # compares by a factor of 3.
2025-07-02 04:52:32.646 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.646 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.647 # of the computation is cached by cruncher
2025-07-02 04:52:32.647 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.647 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.647 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.647 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.647 if best_ratio < cutoff:
2025-07-02 04:52:32.647 # no non-identical "pretty close" pair
2025-07-02 04:52:32.647 if eqi is None:
2025-07-02 04:52:32.647 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.647 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.647 return
2025-07-02 04:52:32.647 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.647 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.647 else:
2025-07-02 04:52:32.647 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.647 eqi = None
2025-07-02 04:52:32.647
2025-07-02 04:52:32.647 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.647 # identical
2025-07-02 04:52:32.647
2025-07-02 04:52:32.647 # pump out diffs from before the synch point
2025-07-02 04:52:32.648 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.648
2025-07-02 04:52:32.648 # do intraline marking on the synch pair
2025-07-02 04:52:32.648 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.650 if eqi is None:
2025-07-02 04:52:32.650 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.650 atags = btags = ""
2025-07-02 04:52:32.650 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.650 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.650 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.650 if tag == 'replace':
2025-07-02 04:52:32.650 atags += '^' * la
2025-07-02 04:52:32.650 btags += '^' * lb
2025-07-02 04:52:32.650 elif tag == 'delete':
2025-07-02 04:52:32.650 atags += '-' * la
2025-07-02 04:52:32.650 elif tag == 'insert':
2025-07-02 04:52:32.650 btags += '+' * lb
2025-07-02 04:52:32.650 elif tag == 'equal':
2025-07-02 04:52:32.650 atags += ' ' * la
2025-07-02 04:52:32.650 btags += ' ' * lb
2025-07-02 04:52:32.650 else:
2025-07-02 04:52:32.650 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.650 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.651 else:
2025-07-02 04:52:32.651 # the synch pair is identical
2025-07-02 04:52:32.651 yield ' ' + aelt
2025-07-02 04:52:32.651
2025-07-02 04:52:32.651 # pump out diffs from after the synch point
2025-07-02 04:52:32.651 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.651
2025-07-02 04:52:32.651 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.651 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.651
2025-07-02 04:52:32.651 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.651 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.651 alo = 263, ahi = 1101
2025-07-02 04:52:32.651 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.651 blo = 263, bhi = 1101
2025-07-02 04:52:32.651
2025-07-02 04:52:32.651 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.651 g = []
2025-07-02 04:52:32.651 if alo < ahi:
2025-07-02 04:52:32.651 if blo < bhi:
2025-07-02 04:52:32.651 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.652 else:
2025-07-02 04:52:32.652 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.652 elif blo < bhi:
2025-07-02 04:52:32.652 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.652
2025-07-02 04:52:32.652 > yield from g
2025-07-02 04:52:32.652
2025-07-02 04:52:32.652 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.652 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.652
2025-07-02 04:52:32.652 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.652 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.652 alo = 263, ahi = 1101
2025-07-02 04:52:32.652 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.652 blo = 263, bhi = 1101
2025-07-02 04:52:32.652
2025-07-02 04:52:32.652 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.652 r"""
2025-07-02 04:52:32.652 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.652 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.652 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.653 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.653
2025-07-02 04:52:32.653 Example:
2025-07-02 04:52:32.653
2025-07-02 04:52:32.653 >>> d = Differ()
2025-07-02 04:52:32.653 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.653 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.653 >>> print(''.join(results), end="")
2025-07-02 04:52:32.653 - abcDefghiJkl
2025-07-02 04:52:32.653 + abcdefGhijkl
2025-07-02 04:52:32.653 """
2025-07-02 04:52:32.653
2025-07-02 04:52:32.653 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.653 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.653 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.653 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.653 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.653
2025-07-02 04:52:32.653 # search for the pair that matches best without being identical
2025-07-02 04:52:32.654 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.654 # on junk -- unless we have to)
2025-07-02 04:52:32.654 for j in range(blo, bhi):
2025-07-02 04:52:32.654 bj = b[j]
2025-07-02 04:52:32.654 cruncher.set_seq2(bj)
2025-07-02 04:52:32.654 for i in range(alo, ahi):
2025-07-02 04:52:32.654 ai = a[i]
2025-07-02 04:52:32.654 if ai == bj:
2025-07-02 04:52:32.654 if eqi is None:
2025-07-02 04:52:32.654 eqi, eqj = i, j
2025-07-02 04:52:32.654 continue
2025-07-02 04:52:32.654 cruncher.set_seq1(ai)
2025-07-02 04:52:32.654 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.654 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.654 # compares by a factor of 3.
2025-07-02 04:52:32.654 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.654 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.654 # of the computation is cached by cruncher
2025-07-02 04:52:32.654 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.654 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.654 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.654 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.655 if best_ratio < cutoff:
2025-07-02 04:52:32.655 # no non-identical "pretty close" pair
2025-07-02 04:52:32.655 if eqi is None:
2025-07-02 04:52:32.655 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.655 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.655 return
2025-07-02 04:52:32.655 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.655 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.655 else:
2025-07-02 04:52:32.655 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.655 eqi = None
2025-07-02 04:52:32.655
2025-07-02 04:52:32.655 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.655 # identical
2025-07-02 04:52:32.655
2025-07-02 04:52:32.655 # pump out diffs from before the synch point
2025-07-02 04:52:32.655 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.655
2025-07-02 04:52:32.655 # do intraline marking on the synch pair
2025-07-02 04:52:32.656 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.656 if eqi is None:
2025-07-02 04:52:32.656 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.656 atags = btags = ""
2025-07-02 04:52:32.656 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.656 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.656 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.656 if tag == 'replace':
2025-07-02 04:52:32.656 atags += '^' * la
2025-07-02 04:52:32.656 btags += '^' * lb
2025-07-02 04:52:32.656 elif tag == 'delete':
2025-07-02 04:52:32.656 atags += '-' * la
2025-07-02 04:52:32.656 elif tag == 'insert':
2025-07-02 04:52:32.656 btags += '+' * lb
2025-07-02 04:52:32.656 elif tag == 'equal':
2025-07-02 04:52:32.656 atags += ' ' * la
2025-07-02 04:52:32.656 btags += ' ' * lb
2025-07-02 04:52:32.656 else:
2025-07-02 04:52:32.656 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.656 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.656 else:
2025-07-02 04:52:32.657 # the synch pair is identical
2025-07-02 04:52:32.657 yield ' ' + aelt
2025-07-02 04:52:32.657
2025-07-02 04:52:32.657 # pump out diffs from after the synch point
2025-07-02 04:52:32.657 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.657
2025-07-02 04:52:32.657 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.657 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.657
2025-07-02 04:52:32.657 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.657 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.657 alo = 264, ahi = 1101
2025-07-02 04:52:32.657 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.657 blo = 264, bhi = 1101
2025-07-02 04:52:32.657
2025-07-02 04:52:32.657 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.657 g = []
2025-07-02 04:52:32.657 if alo < ahi:
2025-07-02 04:52:32.657 if blo < bhi:
2025-07-02 04:52:32.657 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.658 else:
2025-07-02 04:52:32.658 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.658 elif blo < bhi:
2025-07-02 04:52:32.658 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.658
2025-07-02 04:52:32.658 > yield from g
2025-07-02 04:52:32.658
2025-07-02 04:52:32.658 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.658 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.658
2025-07-02 04:52:32.658 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.658 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.658 alo = 264, ahi = 1101
2025-07-02 04:52:32.658 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.658 blo = 264, bhi = 1101
2025-07-02 04:52:32.658
2025-07-02 04:52:32.658 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.658 r"""
2025-07-02 04:52:32.658 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.659 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.659 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.659 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.659
2025-07-02 04:52:32.659 Example:
2025-07-02 04:52:32.659
2025-07-02 04:52:32.659 >>> d = Differ()
2025-07-02 04:52:32.659 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.659 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.659 >>> print(''.join(results), end="")
2025-07-02 04:52:32.659 - abcDefghiJkl
2025-07-02 04:52:32.659 + abcdefGhijkl
2025-07-02 04:52:32.659 """
2025-07-02 04:52:32.659
2025-07-02 04:52:32.659 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.659 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.659 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.659 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.659 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.660
2025-07-02 04:52:32.660 # search for the pair that matches best without being identical
2025-07-02 04:52:32.660 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.660 # on junk -- unless we have to)
2025-07-02 04:52:32.660 for j in range(blo, bhi):
2025-07-02 04:52:32.660 bj = b[j]
2025-07-02 04:52:32.660 cruncher.set_seq2(bj)
2025-07-02 04:52:32.660 for i in range(alo, ahi):
2025-07-02 04:52:32.660 ai = a[i]
2025-07-02 04:52:32.660 if ai == bj:
2025-07-02 04:52:32.660 if eqi is None:
2025-07-02 04:52:32.660 eqi, eqj = i, j
2025-07-02 04:52:32.660 continue
2025-07-02 04:52:32.660 cruncher.set_seq1(ai)
2025-07-02 04:52:32.660 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.660 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.660 # compares by a factor of 3.
2025-07-02 04:52:32.660 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.660 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.660 # of the computation is cached by cruncher
2025-07-02 04:52:32.660 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.661 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.661 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.661 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.661 if best_ratio < cutoff:
2025-07-02 04:52:32.661 # no non-identical "pretty close" pair
2025-07-02 04:52:32.661 if eqi is None:
2025-07-02 04:52:32.661 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.661 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.661 return
2025-07-02 04:52:32.661 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.661 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.661 else:
2025-07-02 04:52:32.661 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.661 eqi = None
2025-07-02 04:52:32.661
2025-07-02 04:52:32.661 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.661 # identical
2025-07-02 04:52:32.661
2025-07-02 04:52:32.661 # pump out diffs from before the synch point
2025-07-02 04:52:32.661 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.661
2025-07-02 04:52:32.662 # do intraline marking on the synch pair
2025-07-02 04:52:32.662 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.662 if eqi is None:
2025-07-02 04:52:32.662 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.662 atags = btags = ""
2025-07-02 04:52:32.662 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.662 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.662 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.662 if tag == 'replace':
2025-07-02 04:52:32.662 atags += '^' * la
2025-07-02 04:52:32.662 btags += '^' * lb
2025-07-02 04:52:32.662 elif tag == 'delete':
2025-07-02 04:52:32.662 atags += '-' * la
2025-07-02 04:52:32.662 elif tag == 'insert':
2025-07-02 04:52:32.662 btags += '+' * lb
2025-07-02 04:52:32.662 elif tag == 'equal':
2025-07-02 04:52:32.662 atags += ' ' * la
2025-07-02 04:52:32.662 btags += ' ' * lb
2025-07-02 04:52:32.662 else:
2025-07-02 04:52:32.662 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.662 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.662 else:
2025-07-02 04:52:32.663 # the synch pair is identical
2025-07-02 04:52:32.663 yield ' ' + aelt
2025-07-02 04:52:32.663
2025-07-02 04:52:32.663 # pump out diffs from after the synch point
2025-07-02 04:52:32.663 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.663
2025-07-02 04:52:32.663 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.663 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.663
2025-07-02 04:52:32.663 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.663 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.663 alo = 265, ahi = 1101
2025-07-02 04:52:32.663 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.663 blo = 265, bhi = 1101
2025-07-02 04:52:32.663
2025-07-02 04:52:32.663 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.663 g = []
2025-07-02 04:52:32.663 if alo < ahi:
2025-07-02 04:52:32.663 if blo < bhi:
2025-07-02 04:52:32.663 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.663 else:
2025-07-02 04:52:32.664 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.664 elif blo < bhi:
2025-07-02 04:52:32.664 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.664
2025-07-02 04:52:32.664 > yield from g
2025-07-02 04:52:32.664
2025-07-02 04:52:32.664 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.664 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.664
2025-07-02 04:52:32.664 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.664 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.664 alo = 265, ahi = 1101
2025-07-02 04:52:32.664 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.664 blo = 265, bhi = 1101
2025-07-02 04:52:32.664
2025-07-02 04:52:32.664 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.664 r"""
2025-07-02 04:52:32.664 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.664 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.664 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.664 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.665
2025-07-02 04:52:32.665 Example:
2025-07-02 04:52:32.665
2025-07-02 04:52:32.665 >>> d = Differ()
2025-07-02 04:52:32.665 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.665 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.665 >>> print(''.join(results), end="")
2025-07-02 04:52:32.665 - abcDefghiJkl
2025-07-02 04:52:32.665 + abcdefGhijkl
2025-07-02 04:52:32.665 """
2025-07-02 04:52:32.665
2025-07-02 04:52:32.665 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.665 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.665 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.665 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.665 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.665
2025-07-02 04:52:32.665 # search for the pair that matches best without being identical
2025-07-02 04:52:32.666 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.666 # on junk -- unless we have to)
2025-07-02 04:52:32.666 for j in range(blo, bhi):
2025-07-02 04:52:32.666 bj = b[j]
2025-07-02 04:52:32.666 cruncher.set_seq2(bj)
2025-07-02 04:52:32.666 for i in range(alo, ahi):
2025-07-02 04:52:32.666 ai = a[i]
2025-07-02 04:52:32.666 if ai == bj:
2025-07-02 04:52:32.666 if eqi is None:
2025-07-02 04:52:32.666 eqi, eqj = i, j
2025-07-02 04:52:32.666 continue
2025-07-02 04:52:32.666 cruncher.set_seq1(ai)
2025-07-02 04:52:32.666 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.666 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.666 # compares by a factor of 3.
2025-07-02 04:52:32.666 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.666 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.666 # of the computation is cached by cruncher
2025-07-02 04:52:32.666 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.666 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.666 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.667 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.667 if best_ratio < cutoff:
2025-07-02 04:52:32.667 # no non-identical "pretty close" pair
2025-07-02 04:52:32.667 if eqi is None:
2025-07-02 04:52:32.667 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.667 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.667 return
2025-07-02 04:52:32.667 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.667 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.667 else:
2025-07-02 04:52:32.667 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.667 eqi = None
2025-07-02 04:52:32.667
2025-07-02 04:52:32.667 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.667 # identical
2025-07-02 04:52:32.667
2025-07-02 04:52:32.667 # pump out diffs from before the synch point
2025-07-02 04:52:32.667 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.667
2025-07-02 04:52:32.667 # do intraline marking on the synch pair
2025-07-02 04:52:32.667 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.668 if eqi is None:
2025-07-02 04:52:32.668 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.668 atags = btags = ""
2025-07-02 04:52:32.668 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.668 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.668 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.668 if tag == 'replace':
2025-07-02 04:52:32.668 atags += '^' * la
2025-07-02 04:52:32.668 btags += '^' * lb
2025-07-02 04:52:32.668 elif tag == 'delete':
2025-07-02 04:52:32.668 atags += '-' * la
2025-07-02 04:52:32.668 elif tag == 'insert':
2025-07-02 04:52:32.668 btags += '+' * lb
2025-07-02 04:52:32.668 elif tag == 'equal':
2025-07-02 04:52:32.668 atags += ' ' * la
2025-07-02 04:52:32.668 btags += ' ' * lb
2025-07-02 04:52:32.668 else:
2025-07-02 04:52:32.668 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.668 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.668 else:
2025-07-02 04:52:32.669 # the synch pair is identical
2025-07-02 04:52:32.669 yield ' ' + aelt
2025-07-02 04:52:32.669
2025-07-02 04:52:32.669 # pump out diffs from after the synch point
2025-07-02 04:52:32.669 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.669
2025-07-02 04:52:32.669 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.669 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.669
2025-07-02 04:52:32.669 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.669 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.669 alo = 268, ahi = 1101
2025-07-02 04:52:32.669 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.669 blo = 268, bhi = 1101
2025-07-02 04:52:32.669
2025-07-02 04:52:32.669 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.669 g = []
2025-07-02 04:52:32.669 if alo < ahi:
2025-07-02 04:52:32.669 if blo < bhi:
2025-07-02 04:52:32.669 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.669 else:
2025-07-02 04:52:32.670 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.670 elif blo < bhi:
2025-07-02 04:52:32.670 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.670
2025-07-02 04:52:32.670 > yield from g
2025-07-02 04:52:32.670
2025-07-02 04:52:32.670 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.670 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.670
2025-07-02 04:52:32.670 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.670 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.670 alo = 268, ahi = 1101
2025-07-02 04:52:32.670 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.670 blo = 268, bhi = 1101
2025-07-02 04:52:32.670
2025-07-02 04:52:32.670 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.670 r"""
2025-07-02 04:52:32.670 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.670 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.671 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.671 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.671
2025-07-02 04:52:32.671 Example:
2025-07-02 04:52:32.671
2025-07-02 04:52:32.671 >>> d = Differ()
2025-07-02 04:52:32.671 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.671 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.671 >>> print(''.join(results), end="")
2025-07-02 04:52:32.671 - abcDefghiJkl
2025-07-02 04:52:32.671 + abcdefGhijkl
2025-07-02 04:52:32.671 """
2025-07-02 04:52:32.671
2025-07-02 04:52:32.671 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.671 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.671 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.671 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.671 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.671
2025-07-02 04:52:32.672 # search for the pair that matches best without being identical
2025-07-02 04:52:32.672 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.672 # on junk -- unless we have to)
2025-07-02 04:52:32.672 for j in range(blo, bhi):
2025-07-02 04:52:32.672 bj = b[j]
2025-07-02 04:52:32.672 cruncher.set_seq2(bj)
2025-07-02 04:52:32.672 for i in range(alo, ahi):
2025-07-02 04:52:32.672 ai = a[i]
2025-07-02 04:52:32.672 if ai == bj:
2025-07-02 04:52:32.672 if eqi is None:
2025-07-02 04:52:32.672 eqi, eqj = i, j
2025-07-02 04:52:32.672 continue
2025-07-02 04:52:32.672 cruncher.set_seq1(ai)
2025-07-02 04:52:32.672 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.672 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.672 # compares by a factor of 3.
2025-07-02 04:52:32.672 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.672 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.672 # of the computation is cached by cruncher
2025-07-02 04:52:32.672 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.673 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.673 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.673 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.673 if best_ratio < cutoff:
2025-07-02 04:52:32.673 # no non-identical "pretty close" pair
2025-07-02 04:52:32.673 if eqi is None:
2025-07-02 04:52:32.673 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.673 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.673 return
2025-07-02 04:52:32.673 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.673 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.673 else:
2025-07-02 04:52:32.673 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.673 eqi = None
2025-07-02 04:52:32.673
2025-07-02 04:52:32.673 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.673 # identical
2025-07-02 04:52:32.673
2025-07-02 04:52:32.673 # pump out diffs from before the synch point
2025-07-02 04:52:32.673 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.673
2025-07-02 04:52:32.674 # do intraline marking on the synch pair
2025-07-02 04:52:32.674 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.674 if eqi is None:
2025-07-02 04:52:32.674 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.674 atags = btags = ""
2025-07-02 04:52:32.674 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.674 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.674 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.674 if tag == 'replace':
2025-07-02 04:52:32.674 atags += '^' * la
2025-07-02 04:52:32.674 btags += '^' * lb
2025-07-02 04:52:32.674 elif tag == 'delete':
2025-07-02 04:52:32.674 atags += '-' * la
2025-07-02 04:52:32.674 elif tag == 'insert':
2025-07-02 04:52:32.674 btags += '+' * lb
2025-07-02 04:52:32.674 elif tag == 'equal':
2025-07-02 04:52:32.674 atags += ' ' * la
2025-07-02 04:52:32.674 btags += ' ' * lb
2025-07-02 04:52:32.674 else:
2025-07-02 04:52:32.674 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.674 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.675 else:
2025-07-02 04:52:32.675 # the synch pair is identical
2025-07-02 04:52:32.675 yield ' ' + aelt
2025-07-02 04:52:32.675
2025-07-02 04:52:32.675 # pump out diffs from after the synch point
2025-07-02 04:52:32.675 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.675
2025-07-02 04:52:32.675 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.675 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.675
2025-07-02 04:52:32.675 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.675 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.675 alo = 269, ahi = 1101
2025-07-02 04:52:32.675 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.675 blo = 269, bhi = 1101
2025-07-02 04:52:32.675
2025-07-02 04:52:32.675 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.675 g = []
2025-07-02 04:52:32.675 if alo < ahi:
2025-07-02 04:52:32.676 if blo < bhi:
2025-07-02 04:52:32.676 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.676 else:
2025-07-02 04:52:32.676 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.676 elif blo < bhi:
2025-07-02 04:52:32.676 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.676
2025-07-02 04:52:32.676 > yield from g
2025-07-02 04:52:32.676
2025-07-02 04:52:32.676 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.676 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.676
2025-07-02 04:52:32.676 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.676 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.676 alo = 269, ahi = 1101
2025-07-02 04:52:32.676 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.676 blo = 269, bhi = 1101
2025-07-02 04:52:32.676
2025-07-02 04:52:32.676 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.676 r"""
2025-07-02 04:52:32.677 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.677 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.677 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.677 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.677
2025-07-02 04:52:32.677 Example:
2025-07-02 04:52:32.677
2025-07-02 04:52:32.677 >>> d = Differ()
2025-07-02 04:52:32.677 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.677 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.677 >>> print(''.join(results), end="")
2025-07-02 04:52:32.677 - abcDefghiJkl
2025-07-02 04:52:32.677 + abcdefGhijkl
2025-07-02 04:52:32.677 """
2025-07-02 04:52:32.677
2025-07-02 04:52:32.677 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.677 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.677 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.677 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.678 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.678
2025-07-02 04:52:32.678 # search for the pair that matches best without being identical
2025-07-02 04:52:32.678 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.678 # on junk -- unless we have to)
2025-07-02 04:52:32.678 for j in range(blo, bhi):
2025-07-02 04:52:32.678 bj = b[j]
2025-07-02 04:52:32.678 cruncher.set_seq2(bj)
2025-07-02 04:52:32.678 for i in range(alo, ahi):
2025-07-02 04:52:32.678 ai = a[i]
2025-07-02 04:52:32.678 if ai == bj:
2025-07-02 04:52:32.678 if eqi is None:
2025-07-02 04:52:32.678 eqi, eqj = i, j
2025-07-02 04:52:32.678 continue
2025-07-02 04:52:32.678 cruncher.set_seq1(ai)
2025-07-02 04:52:32.678 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.678 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.678 # compares by a factor of 3.
2025-07-02 04:52:32.678 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.678 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.678 # of the computation is cached by cruncher
2025-07-02 04:52:32.679 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.679 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.679 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.679 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.679 if best_ratio < cutoff:
2025-07-02 04:52:32.679 # no non-identical "pretty close" pair
2025-07-02 04:52:32.679 if eqi is None:
2025-07-02 04:52:32.679 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.679 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.679 return
2025-07-02 04:52:32.679 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.679 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.679 else:
2025-07-02 04:52:32.679 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.679 eqi = None
2025-07-02 04:52:32.679
2025-07-02 04:52:32.679 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.679 # identical
2025-07-02 04:52:32.679
2025-07-02 04:52:32.679 # pump out diffs from before the synch point
2025-07-02 04:52:32.680 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.680
2025-07-02 04:52:32.680 # do intraline marking on the synch pair
2025-07-02 04:52:32.680 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.680 if eqi is None:
2025-07-02 04:52:32.680 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.680 atags = btags = ""
2025-07-02 04:52:32.680 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.680 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.680 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.680 if tag == 'replace':
2025-07-02 04:52:32.680 atags += '^' * la
2025-07-02 04:52:32.680 btags += '^' * lb
2025-07-02 04:52:32.680 elif tag == 'delete':
2025-07-02 04:52:32.680 atags += '-' * la
2025-07-02 04:52:32.680 elif tag == 'insert':
2025-07-02 04:52:32.680 btags += '+' * lb
2025-07-02 04:52:32.680 elif tag == 'equal':
2025-07-02 04:52:32.680 atags += ' ' * la
2025-07-02 04:52:32.680 btags += ' ' * lb
2025-07-02 04:52:32.680 else:
2025-07-02 04:52:32.681 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.681 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.681 else:
2025-07-02 04:52:32.681 # the synch pair is identical
2025-07-02 04:52:32.681 yield ' ' + aelt
2025-07-02 04:52:32.681
2025-07-02 04:52:32.681 # pump out diffs from after the synch point
2025-07-02 04:52:32.681 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.681
2025-07-02 04:52:32.681 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.681 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.681
2025-07-02 04:52:32.681 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.681 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.681 alo = 270, ahi = 1101
2025-07-02 04:52:32.681 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.681 blo = 270, bhi = 1101
2025-07-02 04:52:32.681
2025-07-02 04:52:32.681 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.681 g = []
2025-07-02 04:52:32.682 if alo < ahi:
2025-07-02 04:52:32.682 if blo < bhi:
2025-07-02 04:52:32.682 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.682 else:
2025-07-02 04:52:32.682 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.682 elif blo < bhi:
2025-07-02 04:52:32.682 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.682
2025-07-02 04:52:32.682 > yield from g
2025-07-02 04:52:32.682
2025-07-02 04:52:32.682 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.682 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.682
2025-07-02 04:52:32.682 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.682 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.682 alo = 270, ahi = 1101
2025-07-02 04:52:32.682 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.682 blo = 270, bhi = 1101
2025-07-02 04:52:32.682
2025-07-02 04:52:32.683 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.683 r"""
2025-07-02 04:52:32.683 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.683 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.683 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.683 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.683
2025-07-02 04:52:32.683 Example:
2025-07-02 04:52:32.683
2025-07-02 04:52:32.683 >>> d = Differ()
2025-07-02 04:52:32.683 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.683 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.683 >>> print(''.join(results), end="")
2025-07-02 04:52:32.683 - abcDefghiJkl
2025-07-02 04:52:32.683 + abcdefGhijkl
2025-07-02 04:52:32.683 """
2025-07-02 04:52:32.683
2025-07-02 04:52:32.683 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.683 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.684 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.684 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.684 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.684
2025-07-02 04:52:32.684 # search for the pair that matches best without being identical
2025-07-02 04:52:32.684 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.684 # on junk -- unless we have to)
2025-07-02 04:52:32.684 for j in range(blo, bhi):
2025-07-02 04:52:32.684 bj = b[j]
2025-07-02 04:52:32.684 cruncher.set_seq2(bj)
2025-07-02 04:52:32.684 for i in range(alo, ahi):
2025-07-02 04:52:32.684 ai = a[i]
2025-07-02 04:52:32.684 if ai == bj:
2025-07-02 04:52:32.684 if eqi is None:
2025-07-02 04:52:32.684 eqi, eqj = i, j
2025-07-02 04:52:32.684 continue
2025-07-02 04:52:32.684 cruncher.set_seq1(ai)
2025-07-02 04:52:32.684 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.684 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.684 # compares by a factor of 3.
2025-07-02 04:52:32.685 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.685 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.685 # of the computation is cached by cruncher
2025-07-02 04:52:32.685 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.685 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.685 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.685 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.685 if best_ratio < cutoff:
2025-07-02 04:52:32.685 # no non-identical "pretty close" pair
2025-07-02 04:52:32.685 if eqi is None:
2025-07-02 04:52:32.685 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.685 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.685 return
2025-07-02 04:52:32.685 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.685 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.685 else:
2025-07-02 04:52:32.685 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.685 eqi = None
2025-07-02 04:52:32.685
2025-07-02 04:52:32.685 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.685 # identical
2025-07-02 04:52:32.686
2025-07-02 04:52:32.686 # pump out diffs from before the synch point
2025-07-02 04:52:32.686 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.686
2025-07-02 04:52:32.686 # do intraline marking on the synch pair
2025-07-02 04:52:32.686 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.686 if eqi is None:
2025-07-02 04:52:32.686 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.686 atags = btags = ""
2025-07-02 04:52:32.686 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.686 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.686 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.686 if tag == 'replace':
2025-07-02 04:52:32.686 atags += '^' * la
2025-07-02 04:52:32.686 btags += '^' * lb
2025-07-02 04:52:32.686 elif tag == 'delete':
2025-07-02 04:52:32.686 atags += '-' * la
2025-07-02 04:52:32.686 elif tag == 'insert':
2025-07-02 04:52:32.686 btags += '+' * lb
2025-07-02 04:52:32.687 elif tag == 'equal':
2025-07-02 04:52:32.687 atags += ' ' * la
2025-07-02 04:52:32.687 btags += ' ' * lb
2025-07-02 04:52:32.687 else:
2025-07-02 04:52:32.687 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.687 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.687 else:
2025-07-02 04:52:32.687 # the synch pair is identical
2025-07-02 04:52:32.687 yield ' ' + aelt
2025-07-02 04:52:32.687
2025-07-02 04:52:32.687 # pump out diffs from after the synch point
2025-07-02 04:52:32.687 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.687
2025-07-02 04:52:32.687 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.687 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.687
2025-07-02 04:52:32.687 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.687 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.687 alo = 271, ahi = 1101
2025-07-02 04:52:32.687 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.688 blo = 271, bhi = 1101
2025-07-02 04:52:32.688
2025-07-02 04:52:32.688 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.688 g = []
2025-07-02 04:52:32.688 if alo < ahi:
2025-07-02 04:52:32.688 if blo < bhi:
2025-07-02 04:52:32.688 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.688 else:
2025-07-02 04:52:32.688 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.688 elif blo < bhi:
2025-07-02 04:52:32.688 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.688
2025-07-02 04:52:32.688 > yield from g
2025-07-02 04:52:32.688
2025-07-02 04:52:32.688 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.688 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.688
2025-07-02 04:52:32.688 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.688 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.688 alo = 271, ahi = 1101
2025-07-02 04:52:32.689 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.689 blo = 271, bhi = 1101
2025-07-02 04:52:32.689
2025-07-02 04:52:32.689 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.689 r"""
2025-07-02 04:52:32.689 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.689 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.689 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.689 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.689
2025-07-02 04:52:32.689 Example:
2025-07-02 04:52:32.689
2025-07-02 04:52:32.689 >>> d = Differ()
2025-07-02 04:52:32.689 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.689 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.689 >>> print(''.join(results), end="")
2025-07-02 04:52:32.689 - abcDefghiJkl
2025-07-02 04:52:32.689 + abcdefGhijkl
2025-07-02 04:52:32.689 """
2025-07-02 04:52:32.689
2025-07-02 04:52:32.690 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.690 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.690 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.690 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.690 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.690
2025-07-02 04:52:32.690 # search for the pair that matches best without being identical
2025-07-02 04:52:32.690 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.690 # on junk -- unless we have to)
2025-07-02 04:52:32.690 for j in range(blo, bhi):
2025-07-02 04:52:32.690 bj = b[j]
2025-07-02 04:52:32.690 cruncher.set_seq2(bj)
2025-07-02 04:52:32.690 for i in range(alo, ahi):
2025-07-02 04:52:32.690 ai = a[i]
2025-07-02 04:52:32.690 if ai == bj:
2025-07-02 04:52:32.690 if eqi is None:
2025-07-02 04:52:32.690 eqi, eqj = i, j
2025-07-02 04:52:32.690 continue
2025-07-02 04:52:32.690 cruncher.set_seq1(ai)
2025-07-02 04:52:32.690 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.690 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.691 # compares by a factor of 3.
2025-07-02 04:52:32.691 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.691 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.691 # of the computation is cached by cruncher
2025-07-02 04:52:32.691 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.691 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.691 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.691 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.691 if best_ratio < cutoff:
2025-07-02 04:52:32.691 # no non-identical "pretty close" pair
2025-07-02 04:52:32.691 if eqi is None:
2025-07-02 04:52:32.691 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.691 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.691 return
2025-07-02 04:52:32.691 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.691 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.691 else:
2025-07-02 04:52:32.691 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.691 eqi = None
2025-07-02 04:52:32.691
2025-07-02 04:52:32.692 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.692 # identical
2025-07-02 04:52:32.692
2025-07-02 04:52:32.692 # pump out diffs from before the synch point
2025-07-02 04:52:32.692 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.692
2025-07-02 04:52:32.692 # do intraline marking on the synch pair
2025-07-02 04:52:32.692 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.692 if eqi is None:
2025-07-02 04:52:32.692 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.692 atags = btags = ""
2025-07-02 04:52:32.692 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.692 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.692 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.692 if tag == 'replace':
2025-07-02 04:52:32.692 atags += '^' * la
2025-07-02 04:52:32.692 btags += '^' * lb
2025-07-02 04:52:32.692 elif tag == 'delete':
2025-07-02 04:52:32.692 atags += '-' * la
2025-07-02 04:52:32.692 elif tag == 'insert':
2025-07-02 04:52:32.693 btags += '+' * lb
2025-07-02 04:52:32.693 elif tag == 'equal':
2025-07-02 04:52:32.693 atags += ' ' * la
2025-07-02 04:52:32.693 btags += ' ' * lb
2025-07-02 04:52:32.693 else:
2025-07-02 04:52:32.693 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.693 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.693 else:
2025-07-02 04:52:32.693 # the synch pair is identical
2025-07-02 04:52:32.693 yield ' ' + aelt
2025-07-02 04:52:32.693
2025-07-02 04:52:32.693 # pump out diffs from after the synch point
2025-07-02 04:52:32.693 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.693
2025-07-02 04:52:32.693 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.693 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.693
2025-07-02 04:52:32.693 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.693 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.693 alo = 272, ahi = 1101
2025-07-02 04:52:32.694 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.694 blo = 272, bhi = 1101
2025-07-02 04:52:32.694
2025-07-02 04:52:32.694 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.694 g = []
2025-07-02 04:52:32.694 if alo < ahi:
2025-07-02 04:52:32.694 if blo < bhi:
2025-07-02 04:52:32.694 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.694 else:
2025-07-02 04:52:32.694 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.694 elif blo < bhi:
2025-07-02 04:52:32.694 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.694
2025-07-02 04:52:32.694 > yield from g
2025-07-02 04:52:32.694
2025-07-02 04:52:32.694 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.694 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.694
2025-07-02 04:52:32.694 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.694 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.694 alo = 272, ahi = 1101
2025-07-02 04:52:32.694 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.695 blo = 272, bhi = 1101
2025-07-02 04:52:32.695
2025-07-02 04:52:32.695 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.695 r"""
2025-07-02 04:52:32.695 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.695 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.695 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.695 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.695
2025-07-02 04:52:32.695 Example:
2025-07-02 04:52:32.695
2025-07-02 04:52:32.695 >>> d = Differ()
2025-07-02 04:52:32.695 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.695 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.695 >>> print(''.join(results), end="")
2025-07-02 04:52:32.695 - abcDefghiJkl
2025-07-02 04:52:32.695 + abcdefGhijkl
2025-07-02 04:52:32.695 """
2025-07-02 04:52:32.695
2025-07-02 04:52:32.696 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.696 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.696 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.696 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.696 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.696
2025-07-02 04:52:32.696 # search for the pair that matches best without being identical
2025-07-02 04:52:32.696 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.696 # on junk -- unless we have to)
2025-07-02 04:52:32.696 for j in range(blo, bhi):
2025-07-02 04:52:32.696 bj = b[j]
2025-07-02 04:52:32.696 cruncher.set_seq2(bj)
2025-07-02 04:52:32.696 for i in range(alo, ahi):
2025-07-02 04:52:32.696 ai = a[i]
2025-07-02 04:52:32.696 if ai == bj:
2025-07-02 04:52:32.696 if eqi is None:
2025-07-02 04:52:32.696 eqi, eqj = i, j
2025-07-02 04:52:32.696 continue
2025-07-02 04:52:32.696 cruncher.set_seq1(ai)
2025-07-02 04:52:32.696 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.696 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.697 # compares by a factor of 3.
2025-07-02 04:52:32.697 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.697 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.697 # of the computation is cached by cruncher
2025-07-02 04:52:32.697 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.697 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.697 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.697 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.697 if best_ratio < cutoff:
2025-07-02 04:52:32.697 # no non-identical "pretty close" pair
2025-07-02 04:52:32.697 if eqi is None:
2025-07-02 04:52:32.697 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.697 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.697 return
2025-07-02 04:52:32.697 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.697 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.697 else:
2025-07-02 04:52:32.697 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.697 eqi = None
2025-07-02 04:52:32.697
2025-07-02 04:52:32.697 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.697 # identical
2025-07-02 04:52:32.698
2025-07-02 04:52:32.698 # pump out diffs from before the synch point
2025-07-02 04:52:32.698 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.698
2025-07-02 04:52:32.698 # do intraline marking on the synch pair
2025-07-02 04:52:32.698 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.698 if eqi is None:
2025-07-02 04:52:32.698 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.698 atags = btags = ""
2025-07-02 04:52:32.698 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.698 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.698 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.698 if tag == 'replace':
2025-07-02 04:52:32.698 atags += '^' * la
2025-07-02 04:52:32.698 btags += '^' * lb
2025-07-02 04:52:32.698 elif tag == 'delete':
2025-07-02 04:52:32.698 atags += '-' * la
2025-07-02 04:52:32.698 elif tag == 'insert':
2025-07-02 04:52:32.698 btags += '+' * lb
2025-07-02 04:52:32.698 elif tag == 'equal':
2025-07-02 04:52:32.698 atags += ' ' * la
2025-07-02 04:52:32.699 btags += ' ' * lb
2025-07-02 04:52:32.699 else:
2025-07-02 04:52:32.699 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.699 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.699 else:
2025-07-02 04:52:32.699 # the synch pair is identical
2025-07-02 04:52:32.699 yield ' ' + aelt
2025-07-02 04:52:32.699
2025-07-02 04:52:32.699 # pump out diffs from after the synch point
2025-07-02 04:52:32.699 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.699
2025-07-02 04:52:32.699 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.699 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.699
2025-07-02 04:52:32.699 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.699 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.699 alo = 273, ahi = 1101
2025-07-02 04:52:32.699 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.699 blo = 273, bhi = 1101
2025-07-02 04:52:32.699
2025-07-02 04:52:32.699 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.699 g = []
2025-07-02 04:52:32.700 if alo < ahi:
2025-07-02 04:52:32.700 if blo < bhi:
2025-07-02 04:52:32.700 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.700 else:
2025-07-02 04:52:32.700 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.700 elif blo < bhi:
2025-07-02 04:52:32.700 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.700
2025-07-02 04:52:32.700 > yield from g
2025-07-02 04:52:32.700
2025-07-02 04:52:32.700 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.700 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.700
2025-07-02 04:52:32.700 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.700 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.700 alo = 273, ahi = 1101
2025-07-02 04:52:32.700 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.700 blo = 273, bhi = 1101
2025-07-02 04:52:32.700
2025-07-02 04:52:32.701 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.701 r"""
2025-07-02 04:52:32.701 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.701 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.701 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.701 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.701
2025-07-02 04:52:32.701 Example:
2025-07-02 04:52:32.701
2025-07-02 04:52:32.701 >>> d = Differ()
2025-07-02 04:52:32.701 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.701 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.701 >>> print(''.join(results), end="")
2025-07-02 04:52:32.701 - abcDefghiJkl
2025-07-02 04:52:32.701 + abcdefGhijkl
2025-07-02 04:52:32.701 """
2025-07-02 04:52:32.701
2025-07-02 04:52:32.701 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.701 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.702 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.702 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.702 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.702
2025-07-02 04:52:32.702 # search for the pair that matches best without being identical
2025-07-02 04:52:32.702 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.702 # on junk -- unless we have to)
2025-07-02 04:52:32.702 for j in range(blo, bhi):
2025-07-02 04:52:32.702 bj = b[j]
2025-07-02 04:52:32.702 cruncher.set_seq2(bj)
2025-07-02 04:52:32.702 for i in range(alo, ahi):
2025-07-02 04:52:32.702 ai = a[i]
2025-07-02 04:52:32.702 if ai == bj:
2025-07-02 04:52:32.702 if eqi is None:
2025-07-02 04:52:32.702 eqi, eqj = i, j
2025-07-02 04:52:32.702 continue
2025-07-02 04:52:32.702 cruncher.set_seq1(ai)
2025-07-02 04:52:32.702 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.702 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.702 # compares by a factor of 3.
2025-07-02 04:52:32.703 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.703 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.703 # of the computation is cached by cruncher
2025-07-02 04:52:32.703 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.703 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.703 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.703 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.703 if best_ratio < cutoff:
2025-07-02 04:52:32.703 # no non-identical "pretty close" pair
2025-07-02 04:52:32.703 if eqi is None:
2025-07-02 04:52:32.703 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.703 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.703 return
2025-07-02 04:52:32.703 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.703 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.703 else:
2025-07-02 04:52:32.703 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.703 eqi = None
2025-07-02 04:52:32.703
2025-07-02 04:52:32.703 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.703 # identical
2025-07-02 04:52:32.704
2025-07-02 04:52:32.704 # pump out diffs from before the synch point
2025-07-02 04:52:32.704 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.704
2025-07-02 04:52:32.704 # do intraline marking on the synch pair
2025-07-02 04:52:32.704 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.704 if eqi is None:
2025-07-02 04:52:32.704 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.704 atags = btags = ""
2025-07-02 04:52:32.704 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.704 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.704 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.704 if tag == 'replace':
2025-07-02 04:52:32.704 atags += '^' * la
2025-07-02 04:52:32.704 btags += '^' * lb
2025-07-02 04:52:32.704 elif tag == 'delete':
2025-07-02 04:52:32.704 atags += '-' * la
2025-07-02 04:52:32.704 elif tag == 'insert':
2025-07-02 04:52:32.704 btags += '+' * lb
2025-07-02 04:52:32.704 elif tag == 'equal':
2025-07-02 04:52:32.704 atags += ' ' * la
2025-07-02 04:52:32.705 btags += ' ' * lb
2025-07-02 04:52:32.705 else:
2025-07-02 04:52:32.705 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.705 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.705 else:
2025-07-02 04:52:32.705 # the synch pair is identical
2025-07-02 04:52:32.705 yield ' ' + aelt
2025-07-02 04:52:32.705
2025-07-02 04:52:32.705 # pump out diffs from after the synch point
2025-07-02 04:52:32.705 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.705
2025-07-02 04:52:32.705 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.705 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.705
2025-07-02 04:52:32.705 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.705 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.705 alo = 274, ahi = 1101
2025-07-02 04:52:32.705 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.705 blo = 274, bhi = 1101
2025-07-02 04:52:32.705
2025-07-02 04:52:32.705 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.706 g = []
2025-07-02 04:52:32.706 if alo < ahi:
2025-07-02 04:52:32.706 if blo < bhi:
2025-07-02 04:52:32.706 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.706 else:
2025-07-02 04:52:32.706 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.706 elif blo < bhi:
2025-07-02 04:52:32.706 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.706
2025-07-02 04:52:32.706 > yield from g
2025-07-02 04:52:32.706
2025-07-02 04:52:32.706 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.706 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.706
2025-07-02 04:52:32.706 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.706 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.706 alo = 274, ahi = 1101
2025-07-02 04:52:32.706 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.706 blo = 274, bhi = 1101
2025-07-02 04:52:32.706
2025-07-02 04:52:32.706 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.707 r"""
2025-07-02 04:52:32.707 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.707 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.707 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.707 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.707
2025-07-02 04:52:32.707 Example:
2025-07-02 04:52:32.707
2025-07-02 04:52:32.707 >>> d = Differ()
2025-07-02 04:52:32.707 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.707 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.707 >>> print(''.join(results), end="")
2025-07-02 04:52:32.707 - abcDefghiJkl
2025-07-02 04:52:32.707 + abcdefGhijkl
2025-07-02 04:52:32.707 """
2025-07-02 04:52:32.707
2025-07-02 04:52:32.707 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.707 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.707 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.707 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.708 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.708
2025-07-02 04:52:32.708 # search for the pair that matches best without being identical
2025-07-02 04:52:32.708 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.708 # on junk -- unless we have to)
2025-07-02 04:52:32.708 for j in range(blo, bhi):
2025-07-02 04:52:32.708 bj = b[j]
2025-07-02 04:52:32.708 cruncher.set_seq2(bj)
2025-07-02 04:52:32.708 for i in range(alo, ahi):
2025-07-02 04:52:32.708 ai = a[i]
2025-07-02 04:52:32.708 if ai == bj:
2025-07-02 04:52:32.708 if eqi is None:
2025-07-02 04:52:32.708 eqi, eqj = i, j
2025-07-02 04:52:32.708 continue
2025-07-02 04:52:32.708 cruncher.set_seq1(ai)
2025-07-02 04:52:32.708 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.708 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.708 # compares by a factor of 3.
2025-07-02 04:52:32.708 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.709 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.709 # of the computation is cached by cruncher
2025-07-02 04:52:32.709 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.709 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.709 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.709 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.709 if best_ratio < cutoff:
2025-07-02 04:52:32.709 # no non-identical "pretty close" pair
2025-07-02 04:52:32.709 if eqi is None:
2025-07-02 04:52:32.709 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.709 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.709 return
2025-07-02 04:52:32.709 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.709 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.709 else:
2025-07-02 04:52:32.709 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.709 eqi = None
2025-07-02 04:52:32.709
2025-07-02 04:52:32.709 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.709 # identical
2025-07-02 04:52:32.709
2025-07-02 04:52:32.710 # pump out diffs from before the synch point
2025-07-02 04:52:32.710 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.710
2025-07-02 04:52:32.710 # do intraline marking on the synch pair
2025-07-02 04:52:32.710 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.710 if eqi is None:
2025-07-02 04:52:32.710 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.710 atags = btags = ""
2025-07-02 04:52:32.710 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.710 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.710 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.710 if tag == 'replace':
2025-07-02 04:52:32.710 atags += '^' * la
2025-07-02 04:52:32.710 btags += '^' * lb
2025-07-02 04:52:32.710 elif tag == 'delete':
2025-07-02 04:52:32.710 atags += '-' * la
2025-07-02 04:52:32.710 elif tag == 'insert':
2025-07-02 04:52:32.710 btags += '+' * lb
2025-07-02 04:52:32.710 elif tag == 'equal':
2025-07-02 04:52:32.710 atags += ' ' * la
2025-07-02 04:52:32.710 btags += ' ' * lb
2025-07-02 04:52:32.711 else:
2025-07-02 04:52:32.711 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.711 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.711 else:
2025-07-02 04:52:32.711 # the synch pair is identical
2025-07-02 04:52:32.711 yield ' ' + aelt
2025-07-02 04:52:32.711
2025-07-02 04:52:32.711 # pump out diffs from after the synch point
2025-07-02 04:52:32.711 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.711
2025-07-02 04:52:32.711 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.711 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.711
2025-07-02 04:52:32.711 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.711 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.711 alo = 275, ahi = 1101
2025-07-02 04:52:32.711 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.711 blo = 275, bhi = 1101
2025-07-02 04:52:32.711
2025-07-02 04:52:32.711 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.711 g = []
2025-07-02 04:52:32.712 if alo < ahi:
2025-07-02 04:52:32.712 if blo < bhi:
2025-07-02 04:52:32.712 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.712 else:
2025-07-02 04:52:32.712 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.712 elif blo < bhi:
2025-07-02 04:52:32.712 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.712
2025-07-02 04:52:32.712 > yield from g
2025-07-02 04:52:32.712
2025-07-02 04:52:32.712 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.712 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.712
2025-07-02 04:52:32.712 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.712 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.712 alo = 275, ahi = 1101
2025-07-02 04:52:32.712 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.712 blo = 275, bhi = 1101
2025-07-02 04:52:32.712
2025-07-02 04:52:32.712 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.712 r"""
2025-07-02 04:52:32.712 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.713 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.713 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.713 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.713
2025-07-02 04:52:32.713 Example:
2025-07-02 04:52:32.713
2025-07-02 04:52:32.713 >>> d = Differ()
2025-07-02 04:52:32.713 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.713 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.713 >>> print(''.join(results), end="")
2025-07-02 04:52:32.713 - abcDefghiJkl
2025-07-02 04:52:32.713 + abcdefGhijkl
2025-07-02 04:52:32.713 """
2025-07-02 04:52:32.713
2025-07-02 04:52:32.713 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.713 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.713 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.713 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.713 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.714
2025-07-02 04:52:32.714 # search for the pair that matches best without being identical
2025-07-02 04:52:32.714 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.714 # on junk -- unless we have to)
2025-07-02 04:52:32.714 for j in range(blo, bhi):
2025-07-02 04:52:32.714 bj = b[j]
2025-07-02 04:52:32.714 cruncher.set_seq2(bj)
2025-07-02 04:52:32.714 for i in range(alo, ahi):
2025-07-02 04:52:32.714 ai = a[i]
2025-07-02 04:52:32.714 if ai == bj:
2025-07-02 04:52:32.714 if eqi is None:
2025-07-02 04:52:32.714 eqi, eqj = i, j
2025-07-02 04:52:32.714 continue
2025-07-02 04:52:32.714 cruncher.set_seq1(ai)
2025-07-02 04:52:32.714 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.714 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.714 # compares by a factor of 3.
2025-07-02 04:52:32.714 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.714 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.714 # of the computation is cached by cruncher
2025-07-02 04:52:32.714 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.714 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.715 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.715 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.715 if best_ratio < cutoff:
2025-07-02 04:52:32.715 # no non-identical "pretty close" pair
2025-07-02 04:52:32.715 if eqi is None:
2025-07-02 04:52:32.715 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.715 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.715 return
2025-07-02 04:52:32.715 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.715 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.715 else:
2025-07-02 04:52:32.715 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.715 eqi = None
2025-07-02 04:52:32.715
2025-07-02 04:52:32.715 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.715 # identical
2025-07-02 04:52:32.715
2025-07-02 04:52:32.715 # pump out diffs from before the synch point
2025-07-02 04:52:32.715 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.715
2025-07-02 04:52:32.715 # do intraline marking on the synch pair
2025-07-02 04:52:32.716 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.716 if eqi is None:
2025-07-02 04:52:32.716 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.716 atags = btags = ""
2025-07-02 04:52:32.716 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.716 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.716 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.716 if tag == 'replace':
2025-07-02 04:52:32.716 atags += '^' * la
2025-07-02 04:52:32.716 btags += '^' * lb
2025-07-02 04:52:32.716 elif tag == 'delete':
2025-07-02 04:52:32.716 atags += '-' * la
2025-07-02 04:52:32.716 elif tag == 'insert':
2025-07-02 04:52:32.716 btags += '+' * lb
2025-07-02 04:52:32.716 elif tag == 'equal':
2025-07-02 04:52:32.716 atags += ' ' * la
2025-07-02 04:52:32.716 btags += ' ' * lb
2025-07-02 04:52:32.716 else:
2025-07-02 04:52:32.716 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.716 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.716 else:
2025-07-02 04:52:32.717 # the synch pair is identical
2025-07-02 04:52:32.717 yield ' ' + aelt
2025-07-02 04:52:32.717
2025-07-02 04:52:32.717 # pump out diffs from after the synch point
2025-07-02 04:52:32.717 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.717
2025-07-02 04:52:32.717 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.717 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.717
2025-07-02 04:52:32.717 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.717 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.717 alo = 276, ahi = 1101
2025-07-02 04:52:32.717 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.717 blo = 276, bhi = 1101
2025-07-02 04:52:32.717
2025-07-02 04:52:32.717 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.717 g = []
2025-07-02 04:52:32.717 if alo < ahi:
2025-07-02 04:52:32.717 if blo < bhi:
2025-07-02 04:52:32.717 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.718 else:
2025-07-02 04:52:32.718 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.718 elif blo < bhi:
2025-07-02 04:52:32.718 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.718
2025-07-02 04:52:32.718 > yield from g
2025-07-02 04:52:32.718
2025-07-02 04:52:32.718 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.718 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.718
2025-07-02 04:52:32.718 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.718 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.718 alo = 276, ahi = 1101
2025-07-02 04:52:32.718 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.718 blo = 276, bhi = 1101
2025-07-02 04:52:32.718
2025-07-02 04:52:32.718 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.718 r"""
2025-07-02 04:52:32.719 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.719 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.719 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.719 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.719
2025-07-02 04:52:32.719 Example:
2025-07-02 04:52:32.719
2025-07-02 04:52:32.719 >>> d = Differ()
2025-07-02 04:52:32.719 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.719 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.719 >>> print(''.join(results), end="")
2025-07-02 04:52:32.719 - abcDefghiJkl
2025-07-02 04:52:32.719 + abcdefGhijkl
2025-07-02 04:52:32.719 """
2025-07-02 04:52:32.719
2025-07-02 04:52:32.719 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.719 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.719 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.720 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.720 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.720
2025-07-02 04:52:32.720 # search for the pair that matches best without being identical
2025-07-02 04:52:32.720 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.720 # on junk -- unless we have to)
2025-07-02 04:52:32.720 for j in range(blo, bhi):
2025-07-02 04:52:32.720 bj = b[j]
2025-07-02 04:52:32.720 cruncher.set_seq2(bj)
2025-07-02 04:52:32.720 for i in range(alo, ahi):
2025-07-02 04:52:32.720 ai = a[i]
2025-07-02 04:52:32.720 if ai == bj:
2025-07-02 04:52:32.720 if eqi is None:
2025-07-02 04:52:32.720 eqi, eqj = i, j
2025-07-02 04:52:32.720 continue
2025-07-02 04:52:32.720 cruncher.set_seq1(ai)
2025-07-02 04:52:32.720 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.720 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.720 # compares by a factor of 3.
2025-07-02 04:52:32.720 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.720 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.721 # of the computation is cached by cruncher
2025-07-02 04:52:32.721 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.721 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.721 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.721 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.721 if best_ratio < cutoff:
2025-07-02 04:52:32.721 # no non-identical "pretty close" pair
2025-07-02 04:52:32.721 if eqi is None:
2025-07-02 04:52:32.721 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.721 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.721 return
2025-07-02 04:52:32.721 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.721 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.721 else:
2025-07-02 04:52:32.721 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.721 eqi = None
2025-07-02 04:52:32.721
2025-07-02 04:52:32.721 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.721 # identical
2025-07-02 04:52:32.721
2025-07-02 04:52:32.722 # pump out diffs from before the synch point
2025-07-02 04:52:32.722 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.722
2025-07-02 04:52:32.722 # do intraline marking on the synch pair
2025-07-02 04:52:32.722 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.722 if eqi is None:
2025-07-02 04:52:32.722 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.722 atags = btags = ""
2025-07-02 04:52:32.722 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.722 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.722 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.722 if tag == 'replace':
2025-07-02 04:52:32.722 atags += '^' * la
2025-07-02 04:52:32.722 btags += '^' * lb
2025-07-02 04:52:32.722 elif tag == 'delete':
2025-07-02 04:52:32.722 atags += '-' * la
2025-07-02 04:52:32.722 elif tag == 'insert':
2025-07-02 04:52:32.722 btags += '+' * lb
2025-07-02 04:52:32.722 elif tag == 'equal':
2025-07-02 04:52:32.722 atags += ' ' * la
2025-07-02 04:52:32.722 btags += ' ' * lb
2025-07-02 04:52:32.723 else:
2025-07-02 04:52:32.723 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.723 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.723 else:
2025-07-02 04:52:32.723 # the synch pair is identical
2025-07-02 04:52:32.723 yield ' ' + aelt
2025-07-02 04:52:32.723
2025-07-02 04:52:32.723 # pump out diffs from after the synch point
2025-07-02 04:52:32.723 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.723
2025-07-02 04:52:32.723 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.723 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.723
2025-07-02 04:52:32.723 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.723 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.723 alo = 277, ahi = 1101
2025-07-02 04:52:32.723 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.723 blo = 277, bhi = 1101
2025-07-02 04:52:32.723
2025-07-02 04:52:32.723 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.724 g = []
2025-07-02 04:52:32.724 if alo < ahi:
2025-07-02 04:52:32.724 if blo < bhi:
2025-07-02 04:52:32.724 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.724 else:
2025-07-02 04:52:32.724 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.724 elif blo < bhi:
2025-07-02 04:52:32.724 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.724
2025-07-02 04:52:32.724 > yield from g
2025-07-02 04:52:32.724
2025-07-02 04:52:32.724 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.724 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.724
2025-07-02 04:52:32.724 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.724 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.724 alo = 277, ahi = 1101
2025-07-02 04:52:32.724 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.724 blo = 277, bhi = 1101
2025-07-02 04:52:32.724
2025-07-02 04:52:32.725 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.725 r"""
2025-07-02 04:52:32.725 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.725 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.725 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.725 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.725
2025-07-02 04:52:32.725 Example:
2025-07-02 04:52:32.725
2025-07-02 04:52:32.725 >>> d = Differ()
2025-07-02 04:52:32.725 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.725 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.725 >>> print(''.join(results), end="")
2025-07-02 04:52:32.725 - abcDefghiJkl
2025-07-02 04:52:32.725 + abcdefGhijkl
2025-07-02 04:52:32.725 """
2025-07-02 04:52:32.725
2025-07-02 04:52:32.725 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.726 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.726 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.726 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.726 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.726
2025-07-02 04:52:32.726 # search for the pair that matches best without being identical
2025-07-02 04:52:32.726 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.726 # on junk -- unless we have to)
2025-07-02 04:52:32.726 for j in range(blo, bhi):
2025-07-02 04:52:32.726 bj = b[j]
2025-07-02 04:52:32.726 cruncher.set_seq2(bj)
2025-07-02 04:52:32.726 for i in range(alo, ahi):
2025-07-02 04:52:32.726 ai = a[i]
2025-07-02 04:52:32.726 if ai == bj:
2025-07-02 04:52:32.726 if eqi is None:
2025-07-02 04:52:32.726 eqi, eqj = i, j
2025-07-02 04:52:32.726 continue
2025-07-02 04:52:32.726 cruncher.set_seq1(ai)
2025-07-02 04:52:32.726 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.726 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.727 # compares by a factor of 3.
2025-07-02 04:52:32.727 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.727 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.727 # of the computation is cached by cruncher
2025-07-02 04:52:32.727 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.727 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.727 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.727 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.727 if best_ratio < cutoff:
2025-07-02 04:52:32.727 # no non-identical "pretty close" pair
2025-07-02 04:52:32.727 if eqi is None:
2025-07-02 04:52:32.727 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.727 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.727 return
2025-07-02 04:52:32.727 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.727 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.727 else:
2025-07-02 04:52:32.727 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.727 eqi = None
2025-07-02 04:52:32.727
2025-07-02 04:52:32.728 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.728 # identical
2025-07-02 04:52:32.728
2025-07-02 04:52:32.728 # pump out diffs from before the synch point
2025-07-02 04:52:32.728 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.728
2025-07-02 04:52:32.728 # do intraline marking on the synch pair
2025-07-02 04:52:32.728 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.728 if eqi is None:
2025-07-02 04:52:32.728 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.728 atags = btags = ""
2025-07-02 04:52:32.728 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.728 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.728 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.728 if tag == 'replace':
2025-07-02 04:52:32.728 atags += '^' * la
2025-07-02 04:52:32.728 btags += '^' * lb
2025-07-02 04:52:32.728 elif tag == 'delete':
2025-07-02 04:52:32.728 atags += '-' * la
2025-07-02 04:52:32.728 elif tag == 'insert':
2025-07-02 04:52:32.728 btags += '+' * lb
2025-07-02 04:52:32.728 elif tag == 'equal':
2025-07-02 04:52:32.729 atags += ' ' * la
2025-07-02 04:52:32.729 btags += ' ' * lb
2025-07-02 04:52:32.729 else:
2025-07-02 04:52:32.729 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.729 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.729 else:
2025-07-02 04:52:32.729 # the synch pair is identical
2025-07-02 04:52:32.729 yield ' ' + aelt
2025-07-02 04:52:32.729
2025-07-02 04:52:32.729 # pump out diffs from after the synch point
2025-07-02 04:52:32.729 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.729
2025-07-02 04:52:32.729 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.729 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.729
2025-07-02 04:52:32.729 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.729 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.729 alo = 278, ahi = 1101
2025-07-02 04:52:32.729 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.729 blo = 278, bhi = 1101
2025-07-02 04:52:32.729
2025-07-02 04:52:32.730 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.730 g = []
2025-07-02 04:52:32.730 if alo < ahi:
2025-07-02 04:52:32.730 if blo < bhi:
2025-07-02 04:52:32.730 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.730 else:
2025-07-02 04:52:32.730 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.730 elif blo < bhi:
2025-07-02 04:52:32.730 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.730
2025-07-02 04:52:32.730 > yield from g
2025-07-02 04:52:32.730
2025-07-02 04:52:32.730 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.730 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.730
2025-07-02 04:52:32.730 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.730 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.730 alo = 278, ahi = 1101
2025-07-02 04:52:32.730 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.730 blo = 278, bhi = 1101
2025-07-02 04:52:32.730
2025-07-02 04:52:32.730 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.731 r"""
2025-07-02 04:52:32.731 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.731 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.731 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.731 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.731
2025-07-02 04:52:32.731 Example:
2025-07-02 04:52:32.731
2025-07-02 04:52:32.731 >>> d = Differ()
2025-07-02 04:52:32.731 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.731 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.731 >>> print(''.join(results), end="")
2025-07-02 04:52:32.731 - abcDefghiJkl
2025-07-02 04:52:32.731 + abcdefGhijkl
2025-07-02 04:52:32.731 """
2025-07-02 04:52:32.731
2025-07-02 04:52:32.731 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.731 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.731 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.731 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.732 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.732
2025-07-02 04:52:32.732 # search for the pair that matches best without being identical
2025-07-02 04:52:32.732 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.732 # on junk -- unless we have to)
2025-07-02 04:52:32.732 for j in range(blo, bhi):
2025-07-02 04:52:32.732 bj = b[j]
2025-07-02 04:52:32.732 cruncher.set_seq2(bj)
2025-07-02 04:52:32.732 for i in range(alo, ahi):
2025-07-02 04:52:32.732 ai = a[i]
2025-07-02 04:52:32.732 if ai == bj:
2025-07-02 04:52:32.732 if eqi is None:
2025-07-02 04:52:32.732 eqi, eqj = i, j
2025-07-02 04:52:32.732 continue
2025-07-02 04:52:32.732 cruncher.set_seq1(ai)
2025-07-02 04:52:32.732 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.732 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.732 # compares by a factor of 3.
2025-07-02 04:52:32.732 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.732 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.732 # of the computation is cached by cruncher
2025-07-02 04:52:32.733 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.733 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.733 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.733 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.733 if best_ratio < cutoff:
2025-07-02 04:52:32.733 # no non-identical "pretty close" pair
2025-07-02 04:52:32.733 if eqi is None:
2025-07-02 04:52:32.733 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.733 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.733 return
2025-07-02 04:52:32.733 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.733 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.733 else:
2025-07-02 04:52:32.733 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.733 eqi = None
2025-07-02 04:52:32.733
2025-07-02 04:52:32.733 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.733 # identical
2025-07-02 04:52:32.733
2025-07-02 04:52:32.734 # pump out diffs from before the synch point
2025-07-02 04:52:32.734 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.734
2025-07-02 04:52:32.734 # do intraline marking on the synch pair
2025-07-02 04:52:32.734 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.734 if eqi is None:
2025-07-02 04:52:32.734 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.734 atags = btags = ""
2025-07-02 04:52:32.734 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.734 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.734 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.734 if tag == 'replace':
2025-07-02 04:52:32.734 atags += '^' * la
2025-07-02 04:52:32.734 btags += '^' * lb
2025-07-02 04:52:32.734 elif tag == 'delete':
2025-07-02 04:52:32.734 atags += '-' * la
2025-07-02 04:52:32.734 elif tag == 'insert':
2025-07-02 04:52:32.734 btags += '+' * lb
2025-07-02 04:52:32.734 elif tag == 'equal':
2025-07-02 04:52:32.734 atags += ' ' * la
2025-07-02 04:52:32.735 btags += ' ' * lb
2025-07-02 04:52:32.735 else:
2025-07-02 04:52:32.735 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.735 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.735 else:
2025-07-02 04:52:32.735 # the synch pair is identical
2025-07-02 04:52:32.735 yield ' ' + aelt
2025-07-02 04:52:32.735
2025-07-02 04:52:32.735 # pump out diffs from after the synch point
2025-07-02 04:52:32.735 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.735
2025-07-02 04:52:32.735 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.735 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.735
2025-07-02 04:52:32.735 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.735 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.735 alo = 279, ahi = 1101
2025-07-02 04:52:32.735 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.735 blo = 279, bhi = 1101
2025-07-02 04:52:32.735
2025-07-02 04:52:32.736 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.736 g = []
2025-07-02 04:52:32.736 if alo < ahi:
2025-07-02 04:52:32.736 if blo < bhi:
2025-07-02 04:52:32.736 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.736 else:
2025-07-02 04:52:32.736 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.736 elif blo < bhi:
2025-07-02 04:52:32.736 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.736
2025-07-02 04:52:32.736 > yield from g
2025-07-02 04:52:32.736
2025-07-02 04:52:32.736 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.736 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.736
2025-07-02 04:52:32.736 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.736 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.736 alo = 279, ahi = 1101
2025-07-02 04:52:32.737 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.737 blo = 279, bhi = 1101
2025-07-02 04:52:32.737
2025-07-02 04:52:32.737 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.737 r"""
2025-07-02 04:52:32.737 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.737 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.737 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.737 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.737
2025-07-02 04:52:32.737 Example:
2025-07-02 04:52:32.737
2025-07-02 04:52:32.737 >>> d = Differ()
2025-07-02 04:52:32.737 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.737 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.737 >>> print(''.join(results), end="")
2025-07-02 04:52:32.737 - abcDefghiJkl
2025-07-02 04:52:32.738 + abcdefGhijkl
2025-07-02 04:52:32.738 """
2025-07-02 04:52:32.738
2025-07-02 04:52:32.738 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.738 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.738 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.738 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.738 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.738
2025-07-02 04:52:32.738 # search for the pair that matches best without being identical
2025-07-02 04:52:32.738 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.738 # on junk -- unless we have to)
2025-07-02 04:52:32.738 for j in range(blo, bhi):
2025-07-02 04:52:32.738 bj = b[j]
2025-07-02 04:52:32.739 cruncher.set_seq2(bj)
2025-07-02 04:52:32.739 for i in range(alo, ahi):
2025-07-02 04:52:32.739 ai = a[i]
2025-07-02 04:52:32.739 if ai == bj:
2025-07-02 04:52:32.739 if eqi is None:
2025-07-02 04:52:32.739 eqi, eqj = i, j
2025-07-02 04:52:32.739 continue
2025-07-02 04:52:32.739 cruncher.set_seq1(ai)
2025-07-02 04:52:32.739 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.739 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.739 # compares by a factor of 3.
2025-07-02 04:52:32.739 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.739 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.739 # of the computation is cached by cruncher
2025-07-02 04:52:32.739 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.739 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.739 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.740 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.740 if best_ratio < cutoff:
2025-07-02 04:52:32.740 # no non-identical "pretty close" pair
2025-07-02 04:52:32.740 if eqi is None:
2025-07-02 04:52:32.740 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.740 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.740 return
2025-07-02 04:52:32.740 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.740 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.740 else:
2025-07-02 04:52:32.740 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.740 eqi = None
2025-07-02 04:52:32.740
2025-07-02 04:52:32.740 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.740 # identical
2025-07-02 04:52:32.740
2025-07-02 04:52:32.740 # pump out diffs from before the synch point
2025-07-02 04:52:32.741 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.741
2025-07-02 04:52:32.741 # do intraline marking on the synch pair
2025-07-02 04:52:32.741 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.741 if eqi is None:
2025-07-02 04:52:32.741 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.741 atags = btags = ""
2025-07-02 04:52:32.741 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.741 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.741 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.741 if tag == 'replace':
2025-07-02 04:52:32.741 atags += '^' * la
2025-07-02 04:52:32.741 btags += '^' * lb
2025-07-02 04:52:32.741 elif tag == 'delete':
2025-07-02 04:52:32.741 atags += '-' * la
2025-07-02 04:52:32.741 elif tag == 'insert':
2025-07-02 04:52:32.741 btags += '+' * lb
2025-07-02 04:52:32.742 elif tag == 'equal':
2025-07-02 04:52:32.742 atags += ' ' * la
2025-07-02 04:52:32.742 btags += ' ' * lb
2025-07-02 04:52:32.742 else:
2025-07-02 04:52:32.742 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.742 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.742 else:
2025-07-02 04:52:32.742 # the synch pair is identical
2025-07-02 04:52:32.742 yield ' ' + aelt
2025-07-02 04:52:32.742
2025-07-02 04:52:32.742 # pump out diffs from after the synch point
2025-07-02 04:52:32.742 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.742
2025-07-02 04:52:32.742 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.742 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.742
2025-07-02 04:52:32.742 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.742 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.743 alo = 280, ahi = 1101
2025-07-02 04:52:32.743 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.743 blo = 280, bhi = 1101
2025-07-02 04:52:32.743
2025-07-02 04:52:32.743 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.743 g = []
2025-07-02 04:52:32.743 if alo < ahi:
2025-07-02 04:52:32.743 if blo < bhi:
2025-07-02 04:52:32.743 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.743 else:
2025-07-02 04:52:32.743 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.743 elif blo < bhi:
2025-07-02 04:52:32.743 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.743
2025-07-02 04:52:32.743 > yield from g
2025-07-02 04:52:32.743
2025-07-02 04:52:32.743 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.744 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.744
2025-07-02 04:52:32.744 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.744 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.744 alo = 280, ahi = 1101
2025-07-02 04:52:32.744 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.744 blo = 280, bhi = 1101
2025-07-02 04:52:32.744
2025-07-02 04:52:32.744 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.744 r"""
2025-07-02 04:52:32.744 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.744 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.744 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.744 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.744
2025-07-02 04:52:32.744 Example:
2025-07-02 04:52:32.745
2025-07-02 04:52:32.745 >>> d = Differ()
2025-07-02 04:52:32.745 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.745 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.745 >>> print(''.join(results), end="")
2025-07-02 04:52:32.745 - abcDefghiJkl
2025-07-02 04:52:32.745 + abcdefGhijkl
2025-07-02 04:52:32.745 """
2025-07-02 04:52:32.745
2025-07-02 04:52:32.745 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.745 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.745 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.745 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.745 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.745
2025-07-02 04:52:32.746 # search for the pair that matches best without being identical
2025-07-02 04:52:32.746 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.746 # on junk -- unless we have to)
2025-07-02 04:52:32.746 for j in range(blo, bhi):
2025-07-02 04:52:32.746 bj = b[j]
2025-07-02 04:52:32.746 cruncher.set_seq2(bj)
2025-07-02 04:52:32.746 for i in range(alo, ahi):
2025-07-02 04:52:32.746 ai = a[i]
2025-07-02 04:52:32.746 if ai == bj:
2025-07-02 04:52:32.746 if eqi is None:
2025-07-02 04:52:32.746 eqi, eqj = i, j
2025-07-02 04:52:32.746 continue
2025-07-02 04:52:32.746 cruncher.set_seq1(ai)
2025-07-02 04:52:32.746 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.746 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.746 # compares by a factor of 3.
2025-07-02 04:52:32.746 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.747 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.747 # of the computation is cached by cruncher
2025-07-02 04:52:32.747 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.747 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.747 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.747 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.747 if best_ratio < cutoff:
2025-07-02 04:52:32.747 # no non-identical "pretty close" pair
2025-07-02 04:52:32.747 if eqi is None:
2025-07-02 04:52:32.747 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.747 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.747 return
2025-07-02 04:52:32.747 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.747 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.747 else:
2025-07-02 04:52:32.747 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.747 eqi = None
2025-07-02 04:52:32.748
2025-07-02 04:52:32.748 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.748 # identical
2025-07-02 04:52:32.748
2025-07-02 04:52:32.748 # pump out diffs from before the synch point
2025-07-02 04:52:32.748 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.748
2025-07-02 04:52:32.748 # do intraline marking on the synch pair
2025-07-02 04:52:32.748 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.748 if eqi is None:
2025-07-02 04:52:32.748 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.748 atags = btags = ""
2025-07-02 04:52:32.748 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.748 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.748 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.748 if tag == 'replace':
2025-07-02 04:52:32.748 atags += '^' * la
2025-07-02 04:52:32.749 btags += '^' * lb
2025-07-02 04:52:32.749 elif tag == 'delete':
2025-07-02 04:52:32.749 atags += '-' * la
2025-07-02 04:52:32.749 elif tag == 'insert':
2025-07-02 04:52:32.749 btags += '+' * lb
2025-07-02 04:52:32.749 elif tag == 'equal':
2025-07-02 04:52:32.749 atags += ' ' * la
2025-07-02 04:52:32.749 btags += ' ' * lb
2025-07-02 04:52:32.749 else:
2025-07-02 04:52:32.749 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.749 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.749 else:
2025-07-02 04:52:32.749 # the synch pair is identical
2025-07-02 04:52:32.749 yield ' ' + aelt
2025-07-02 04:52:32.749
2025-07-02 04:52:32.749 # pump out diffs from after the synch point
2025-07-02 04:52:32.750 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.750
2025-07-02 04:52:32.750 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.750 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.750
2025-07-02 04:52:32.750 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.750 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.750 alo = 281, ahi = 1101
2025-07-02 04:52:32.750 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.750 blo = 281, bhi = 1101
2025-07-02 04:52:32.750
2025-07-02 04:52:32.750 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.750 g = []
2025-07-02 04:52:32.750 if alo < ahi:
2025-07-02 04:52:32.750 if blo < bhi:
2025-07-02 04:52:32.750 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.751 else:
2025-07-02 04:52:32.751 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.751 elif blo < bhi:
2025-07-02 04:52:32.751 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.751
2025-07-02 04:52:32.751 > yield from g
2025-07-02 04:52:32.751
2025-07-02 04:52:32.751 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.751 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.751
2025-07-02 04:52:32.751 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.751 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.751 alo = 281, ahi = 1101
2025-07-02 04:52:32.751 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.751 blo = 281, bhi = 1101
2025-07-02 04:52:32.751
2025-07-02 04:52:32.751 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.752 r"""
2025-07-02 04:52:32.752 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.752 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.752 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.752 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.752
2025-07-02 04:52:32.752 Example:
2025-07-02 04:52:32.752
2025-07-02 04:52:32.752 >>> d = Differ()
2025-07-02 04:52:32.752 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.752 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.752 >>> print(''.join(results), end="")
2025-07-02 04:52:32.752 - abcDefghiJkl
2025-07-02 04:52:32.752 + abcdefGhijkl
2025-07-02 04:52:32.752 """
2025-07-02 04:52:32.753
2025-07-02 04:52:32.753 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.753 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.753 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.753 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.753 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.753
2025-07-02 04:52:32.753 # search for the pair that matches best without being identical
2025-07-02 04:52:32.753 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.753 # on junk -- unless we have to)
2025-07-02 04:52:32.753 for j in range(blo, bhi):
2025-07-02 04:52:32.753 bj = b[j]
2025-07-02 04:52:32.753 cruncher.set_seq2(bj)
2025-07-02 04:52:32.753 for i in range(alo, ahi):
2025-07-02 04:52:32.753 ai = a[i]
2025-07-02 04:52:32.753 if ai == bj:
2025-07-02 04:52:32.753 if eqi is None:
2025-07-02 04:52:32.754 eqi, eqj = i, j
2025-07-02 04:52:32.754 continue
2025-07-02 04:52:32.754 cruncher.set_seq1(ai)
2025-07-02 04:52:32.754 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.754 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.754 # compares by a factor of 3.
2025-07-02 04:52:32.754 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.754 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.754 # of the computation is cached by cruncher
2025-07-02 04:52:32.754 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.754 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.754 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.754 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.754 if best_ratio < cutoff:
2025-07-02 04:52:32.754 # no non-identical "pretty close" pair
2025-07-02 04:52:32.754 if eqi is None:
2025-07-02 04:52:32.754 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.755 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.755 return
2025-07-02 04:52:32.755 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.755 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.755 else:
2025-07-02 04:52:32.755 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.755 eqi = None
2025-07-02 04:52:32.755
2025-07-02 04:52:32.755 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.755 # identical
2025-07-02 04:52:32.755
2025-07-02 04:52:32.755 # pump out diffs from before the synch point
2025-07-02 04:52:32.755 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.755
2025-07-02 04:52:32.755 # do intraline marking on the synch pair
2025-07-02 04:52:32.755 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.755 if eqi is None:
2025-07-02 04:52:32.755 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.755 atags = btags = ""
2025-07-02 04:52:32.755 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.756 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.756 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.756 if tag == 'replace':
2025-07-02 04:52:32.756 atags += '^' * la
2025-07-02 04:52:32.756 btags += '^' * lb
2025-07-02 04:52:32.756 elif tag == 'delete':
2025-07-02 04:52:32.756 atags += '-' * la
2025-07-02 04:52:32.756 elif tag == 'insert':
2025-07-02 04:52:32.756 btags += '+' * lb
2025-07-02 04:52:32.756 elif tag == 'equal':
2025-07-02 04:52:32.756 atags += ' ' * la
2025-07-02 04:52:32.756 btags += ' ' * lb
2025-07-02 04:52:32.756 else:
2025-07-02 04:52:32.756 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.756 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.756 else:
2025-07-02 04:52:32.756 # the synch pair is identical
2025-07-02 04:52:32.756 yield ' ' + aelt
2025-07-02 04:52:32.756
2025-07-02 04:52:32.757 # pump out diffs from after the synch point
2025-07-02 04:52:32.757 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.757
2025-07-02 04:52:32.757 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.757 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.757
2025-07-02 04:52:32.757 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.757 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.757 alo = 282, ahi = 1101
2025-07-02 04:52:32.757 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.757 blo = 282, bhi = 1101
2025-07-02 04:52:32.757
2025-07-02 04:52:32.757 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.757 g = []
2025-07-02 04:52:32.757 if alo < ahi:
2025-07-02 04:52:32.757 if blo < bhi:
2025-07-02 04:52:32.757 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.757 else:
2025-07-02 04:52:32.757 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.757 elif blo < bhi:
2025-07-02 04:52:32.758 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.758
2025-07-02 04:52:32.758 > yield from g
2025-07-02 04:52:32.758
2025-07-02 04:52:32.758 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.758 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.758
2025-07-02 04:52:32.758 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.758 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.758 alo = 282, ahi = 1101
2025-07-02 04:52:32.758 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.758 blo = 282, bhi = 1101
2025-07-02 04:52:32.758
2025-07-02 04:52:32.758 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.758 r"""
2025-07-02 04:52:32.758 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.758 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.758 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.758 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.759
2025-07-02 04:52:32.759 Example:
2025-07-02 04:52:32.759
2025-07-02 04:52:32.759 >>> d = Differ()
2025-07-02 04:52:32.759 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.759 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.759 >>> print(''.join(results), end="")
2025-07-02 04:52:32.759 - abcDefghiJkl
2025-07-02 04:52:32.759 + abcdefGhijkl
2025-07-02 04:52:32.759 """
2025-07-02 04:52:32.759
2025-07-02 04:52:32.759 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.759 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.759 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.759 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.759 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.759
2025-07-02 04:52:32.759 # search for the pair that matches best without being identical
2025-07-02 04:52:32.759 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.760 # on junk -- unless we have to)
2025-07-02 04:52:32.760 for j in range(blo, bhi):
2025-07-02 04:52:32.760 bj = b[j]
2025-07-02 04:52:32.760 cruncher.set_seq2(bj)
2025-07-02 04:52:32.760 for i in range(alo, ahi):
2025-07-02 04:52:32.760 ai = a[i]
2025-07-02 04:52:32.760 if ai == bj:
2025-07-02 04:52:32.760 if eqi is None:
2025-07-02 04:52:32.760 eqi, eqj = i, j
2025-07-02 04:52:32.760 continue
2025-07-02 04:52:32.760 cruncher.set_seq1(ai)
2025-07-02 04:52:32.760 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.760 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.760 # compares by a factor of 3.
2025-07-02 04:52:32.760 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.760 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.760 # of the computation is cached by cruncher
2025-07-02 04:52:32.760 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.760 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.760 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.760 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.761 if best_ratio < cutoff:
2025-07-02 04:52:32.761 # no non-identical "pretty close" pair
2025-07-02 04:52:32.761 if eqi is None:
2025-07-02 04:52:32.761 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.761 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.761 return
2025-07-02 04:52:32.761 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.761 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.761 else:
2025-07-02 04:52:32.761 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.761 eqi = None
2025-07-02 04:52:32.761
2025-07-02 04:52:32.761 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.761 # identical
2025-07-02 04:52:32.761
2025-07-02 04:52:32.761 # pump out diffs from before the synch point
2025-07-02 04:52:32.761 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.761
2025-07-02 04:52:32.761 # do intraline marking on the synch pair
2025-07-02 04:52:32.761 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.762 if eqi is None:
2025-07-02 04:52:32.762 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.762 atags = btags = ""
2025-07-02 04:52:32.762 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.762 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.762 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.762 if tag == 'replace':
2025-07-02 04:52:32.762 atags += '^' * la
2025-07-02 04:52:32.762 btags += '^' * lb
2025-07-02 04:52:32.762 elif tag == 'delete':
2025-07-02 04:52:32.762 atags += '-' * la
2025-07-02 04:52:32.762 elif tag == 'insert':
2025-07-02 04:52:32.762 btags += '+' * lb
2025-07-02 04:52:32.762 elif tag == 'equal':
2025-07-02 04:52:32.762 atags += ' ' * la
2025-07-02 04:52:32.762 btags += ' ' * lb
2025-07-02 04:52:32.762 else:
2025-07-02 04:52:32.762 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.763 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.763 else:
2025-07-02 04:52:32.763 # the synch pair is identical
2025-07-02 04:52:32.763 yield ' ' + aelt
2025-07-02 04:52:32.763
2025-07-02 04:52:32.763 # pump out diffs from after the synch point
2025-07-02 04:52:32.763 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.763
2025-07-02 04:52:32.763 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.763 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.763
2025-07-02 04:52:32.763 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.763 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.763 alo = 283, ahi = 1101
2025-07-02 04:52:32.763 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.763 blo = 283, bhi = 1101
2025-07-02 04:52:32.763
2025-07-02 04:52:32.763 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.763 g = []
2025-07-02 04:52:32.763 if alo < ahi:
2025-07-02 04:52:32.764 if blo < bhi:
2025-07-02 04:52:32.764 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.764 else:
2025-07-02 04:52:32.764 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.764 elif blo < bhi:
2025-07-02 04:52:32.764 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.764
2025-07-02 04:52:32.764 > yield from g
2025-07-02 04:52:32.764
2025-07-02 04:52:32.764 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.764 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.764
2025-07-02 04:52:32.764 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.764 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.764 alo = 283, ahi = 1101
2025-07-02 04:52:32.764 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.764 blo = 283, bhi = 1101
2025-07-02 04:52:32.764
2025-07-02 04:52:32.764 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.764 r"""
2025-07-02 04:52:32.764 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.765 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.765 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.765 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.765
2025-07-02 04:52:32.765 Example:
2025-07-02 04:52:32.765
2025-07-02 04:52:32.765 >>> d = Differ()
2025-07-02 04:52:32.765 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.765 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.765 >>> print(''.join(results), end="")
2025-07-02 04:52:32.765 - abcDefghiJkl
2025-07-02 04:52:32.765 + abcdefGhijkl
2025-07-02 04:52:32.765 """
2025-07-02 04:52:32.765
2025-07-02 04:52:32.765 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.765 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.765 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.765 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.766 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.766
2025-07-02 04:52:32.766 # search for the pair that matches best without being identical
2025-07-02 04:52:32.766 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.766 # on junk -- unless we have to)
2025-07-02 04:52:32.766 for j in range(blo, bhi):
2025-07-02 04:52:32.766 bj = b[j]
2025-07-02 04:52:32.766 cruncher.set_seq2(bj)
2025-07-02 04:52:32.766 for i in range(alo, ahi):
2025-07-02 04:52:32.766 ai = a[i]
2025-07-02 04:52:32.766 if ai == bj:
2025-07-02 04:52:32.766 if eqi is None:
2025-07-02 04:52:32.766 eqi, eqj = i, j
2025-07-02 04:52:32.766 continue
2025-07-02 04:52:32.766 cruncher.set_seq1(ai)
2025-07-02 04:52:32.766 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.766 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.766 # compares by a factor of 3.
2025-07-02 04:52:32.766 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.766 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.767 # of the computation is cached by cruncher
2025-07-02 04:52:32.767 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.767 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.767 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.767 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.767 if best_ratio < cutoff:
2025-07-02 04:52:32.767 # no non-identical "pretty close" pair
2025-07-02 04:52:32.767 if eqi is None:
2025-07-02 04:52:32.767 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.767 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.767 return
2025-07-02 04:52:32.767 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.767 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.767 else:
2025-07-02 04:52:32.767 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.767 eqi = None
2025-07-02 04:52:32.767
2025-07-02 04:52:32.767 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.767 # identical
2025-07-02 04:52:32.767
2025-07-02 04:52:32.768 # pump out diffs from before the synch point
2025-07-02 04:52:32.768 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.768
2025-07-02 04:52:32.768 # do intraline marking on the synch pair
2025-07-02 04:52:32.768 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.768 if eqi is None:
2025-07-02 04:52:32.768 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.768 atags = btags = ""
2025-07-02 04:52:32.768 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.768 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.768 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.768 if tag == 'replace':
2025-07-02 04:52:32.768 atags += '^' * la
2025-07-02 04:52:32.768 btags += '^' * lb
2025-07-02 04:52:32.768 elif tag == 'delete':
2025-07-02 04:52:32.768 atags += '-' * la
2025-07-02 04:52:32.768 elif tag == 'insert':
2025-07-02 04:52:32.768 btags += '+' * lb
2025-07-02 04:52:32.768 elif tag == 'equal':
2025-07-02 04:52:32.768 atags += ' ' * la
2025-07-02 04:52:32.768 btags += ' ' * lb
2025-07-02 04:52:32.769 else:
2025-07-02 04:52:32.769 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.769 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.769 else:
2025-07-02 04:52:32.769 # the synch pair is identical
2025-07-02 04:52:32.769 yield ' ' + aelt
2025-07-02 04:52:32.769
2025-07-02 04:52:32.769 # pump out diffs from after the synch point
2025-07-02 04:52:32.769 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.769
2025-07-02 04:52:32.769 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.769 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.769
2025-07-02 04:52:32.769 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.769 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.769 alo = 284, ahi = 1101
2025-07-02 04:52:32.769 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.769 blo = 284, bhi = 1101
2025-07-02 04:52:32.769
2025-07-02 04:52:32.769 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.770 g = []
2025-07-02 04:52:32.770 if alo < ahi:
2025-07-02 04:52:32.770 if blo < bhi:
2025-07-02 04:52:32.770 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.770 else:
2025-07-02 04:52:32.770 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.770 elif blo < bhi:
2025-07-02 04:52:32.770 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.770
2025-07-02 04:52:32.770 > yield from g
2025-07-02 04:52:32.770
2025-07-02 04:52:32.770 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.770 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.770
2025-07-02 04:52:32.770 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.770 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.770 alo = 284, ahi = 1101
2025-07-02 04:52:32.770 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.770 blo = 284, bhi = 1101
2025-07-02 04:52:32.771
2025-07-02 04:52:32.771 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.771 r"""
2025-07-02 04:52:32.771 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.771 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.771 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.771 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.771
2025-07-02 04:52:32.771 Example:
2025-07-02 04:52:32.771
2025-07-02 04:52:32.771 >>> d = Differ()
2025-07-02 04:52:32.771 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.771 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.771 >>> print(''.join(results), end="")
2025-07-02 04:52:32.771 - abcDefghiJkl
2025-07-02 04:52:32.771 + abcdefGhijkl
2025-07-02 04:52:32.771 """
2025-07-02 04:52:32.771
2025-07-02 04:52:32.771 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.772 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.772 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.772 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.772 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.772
2025-07-02 04:52:32.772 # search for the pair that matches best without being identical
2025-07-02 04:52:32.772 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.772 # on junk -- unless we have to)
2025-07-02 04:52:32.772 for j in range(blo, bhi):
2025-07-02 04:52:32.772 bj = b[j]
2025-07-02 04:52:32.772 cruncher.set_seq2(bj)
2025-07-02 04:52:32.772 for i in range(alo, ahi):
2025-07-02 04:52:32.772 ai = a[i]
2025-07-02 04:52:32.772 if ai == bj:
2025-07-02 04:52:32.772 if eqi is None:
2025-07-02 04:52:32.772 eqi, eqj = i, j
2025-07-02 04:52:32.772 continue
2025-07-02 04:52:32.772 cruncher.set_seq1(ai)
2025-07-02 04:52:32.772 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.772 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.773 # compares by a factor of 3.
2025-07-02 04:52:32.773 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.773 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.773 # of the computation is cached by cruncher
2025-07-02 04:52:32.773 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.773 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.773 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.773 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.773 if best_ratio < cutoff:
2025-07-02 04:52:32.773 # no non-identical "pretty close" pair
2025-07-02 04:52:32.773 if eqi is None:
2025-07-02 04:52:32.773 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.773 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.773 return
2025-07-02 04:52:32.773 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.773 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.773 else:
2025-07-02 04:52:32.773 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.773 eqi = None
2025-07-02 04:52:32.773
2025-07-02 04:52:32.773 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.774 # identical
2025-07-02 04:52:32.774
2025-07-02 04:52:32.774 # pump out diffs from before the synch point
2025-07-02 04:52:32.774 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.774
2025-07-02 04:52:32.774 # do intraline marking on the synch pair
2025-07-02 04:52:32.774 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.774 if eqi is None:
2025-07-02 04:52:32.774 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.774 atags = btags = ""
2025-07-02 04:52:32.774 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.774 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.774 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.774 if tag == 'replace':
2025-07-02 04:52:32.774 atags += '^' * la
2025-07-02 04:52:32.774 btags += '^' * lb
2025-07-02 04:52:32.774 elif tag == 'delete':
2025-07-02 04:52:32.774 atags += '-' * la
2025-07-02 04:52:32.774 elif tag == 'insert':
2025-07-02 04:52:32.774 btags += '+' * lb
2025-07-02 04:52:32.775 elif tag == 'equal':
2025-07-02 04:52:32.775 atags += ' ' * la
2025-07-02 04:52:32.775 btags += ' ' * lb
2025-07-02 04:52:32.775 else:
2025-07-02 04:52:32.775 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.775 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.775 else:
2025-07-02 04:52:32.775 # the synch pair is identical
2025-07-02 04:52:32.775 yield ' ' + aelt
2025-07-02 04:52:32.775
2025-07-02 04:52:32.775 # pump out diffs from after the synch point
2025-07-02 04:52:32.775 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.775
2025-07-02 04:52:32.775 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.775 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.775
2025-07-02 04:52:32.775 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.775 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.775 alo = 285, ahi = 1101
2025-07-02 04:52:32.775 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.775 blo = 285, bhi = 1101
2025-07-02 04:52:32.776
2025-07-02 04:52:32.776 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.776 g = []
2025-07-02 04:52:32.776 if alo < ahi:
2025-07-02 04:52:32.776 if blo < bhi:
2025-07-02 04:52:32.776 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.776 else:
2025-07-02 04:52:32.776 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.776 elif blo < bhi:
2025-07-02 04:52:32.776 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.776
2025-07-02 04:52:32.776 > yield from g
2025-07-02 04:52:32.776
2025-07-02 04:52:32.776 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.776 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.776
2025-07-02 04:52:32.776 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.776 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.776 alo = 285, ahi = 1101
2025-07-02 04:52:32.777 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.777 blo = 285, bhi = 1101
2025-07-02 04:52:32.777
2025-07-02 04:52:32.777 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.777 r"""
2025-07-02 04:52:32.777 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.777 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.777 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.777 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.777
2025-07-02 04:52:32.777 Example:
2025-07-02 04:52:32.777
2025-07-02 04:52:32.777 >>> d = Differ()
2025-07-02 04:52:32.777 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.777 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.777 >>> print(''.join(results), end="")
2025-07-02 04:52:32.777 - abcDefghiJkl
2025-07-02 04:52:32.777 + abcdefGhijkl
2025-07-02 04:52:32.778 """
2025-07-02 04:52:32.778
2025-07-02 04:52:32.778 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.778 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.778 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.778 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.778 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.778
2025-07-02 04:52:32.778 # search for the pair that matches best without being identical
2025-07-02 04:52:32.778 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.778 # on junk -- unless we have to)
2025-07-02 04:52:32.778 for j in range(blo, bhi):
2025-07-02 04:52:32.778 bj = b[j]
2025-07-02 04:52:32.778 cruncher.set_seq2(bj)
2025-07-02 04:52:32.778 for i in range(alo, ahi):
2025-07-02 04:52:32.778 ai = a[i]
2025-07-02 04:52:32.778 if ai == bj:
2025-07-02 04:52:32.778 if eqi is None:
2025-07-02 04:52:32.778 eqi, eqj = i, j
2025-07-02 04:52:32.778 continue
2025-07-02 04:52:32.778 cruncher.set_seq1(ai)
2025-07-02 04:52:32.779 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.779 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.779 # compares by a factor of 3.
2025-07-02 04:52:32.779 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.779 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.779 # of the computation is cached by cruncher
2025-07-02 04:52:32.779 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.779 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.779 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.779 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.779 if best_ratio < cutoff:
2025-07-02 04:52:32.779 # no non-identical "pretty close" pair
2025-07-02 04:52:32.779 if eqi is None:
2025-07-02 04:52:32.779 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.779 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.779 return
2025-07-02 04:52:32.779 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.779 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.780 else:
2025-07-02 04:52:32.780 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.780 eqi = None
2025-07-02 04:52:32.780
2025-07-02 04:52:32.780 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.780 # identical
2025-07-02 04:52:32.780
2025-07-02 04:52:32.780 # pump out diffs from before the synch point
2025-07-02 04:52:32.780 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.780
2025-07-02 04:52:32.780 # do intraline marking on the synch pair
2025-07-02 04:52:32.780 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.780 if eqi is None:
2025-07-02 04:52:32.780 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.780 atags = btags = ""
2025-07-02 04:52:32.780 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.780 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.780 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.780 if tag == 'replace':
2025-07-02 04:52:32.780 atags += '^' * la
2025-07-02 04:52:32.780 btags += '^' * lb
2025-07-02 04:52:32.781 elif tag == 'delete':
2025-07-02 04:52:32.781 atags += '-' * la
2025-07-02 04:52:32.781 elif tag == 'insert':
2025-07-02 04:52:32.781 btags += '+' * lb
2025-07-02 04:52:32.781 elif tag == 'equal':
2025-07-02 04:52:32.781 atags += ' ' * la
2025-07-02 04:52:32.781 btags += ' ' * lb
2025-07-02 04:52:32.781 else:
2025-07-02 04:52:32.781 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.781 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.781 else:
2025-07-02 04:52:32.781 # the synch pair is identical
2025-07-02 04:52:32.781 yield ' ' + aelt
2025-07-02 04:52:32.781
2025-07-02 04:52:32.781 # pump out diffs from after the synch point
2025-07-02 04:52:32.781 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.781
2025-07-02 04:52:32.781 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.781 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.781
2025-07-02 04:52:32.782 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.782 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.782 alo = 286, ahi = 1101
2025-07-02 04:52:32.782 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.782 blo = 286, bhi = 1101
2025-07-02 04:52:32.782
2025-07-02 04:52:32.782 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.782 g = []
2025-07-02 04:52:32.782 if alo < ahi:
2025-07-02 04:52:32.782 if blo < bhi:
2025-07-02 04:52:32.782 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.782 else:
2025-07-02 04:52:32.782 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.782 elif blo < bhi:
2025-07-02 04:52:32.782 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.782
2025-07-02 04:52:32.782 > yield from g
2025-07-02 04:52:32.782
2025-07-02 04:52:32.782 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.783 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.783
2025-07-02 04:52:32.783 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.783 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.783 alo = 286, ahi = 1101
2025-07-02 04:52:32.783 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.783 blo = 286, bhi = 1101
2025-07-02 04:52:32.783
2025-07-02 04:52:32.783 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.783 r"""
2025-07-02 04:52:32.783 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.783 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.783 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.783 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.783
2025-07-02 04:52:32.783 Example:
2025-07-02 04:52:32.783
2025-07-02 04:52:32.783 >>> d = Differ()
2025-07-02 04:52:32.783 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.783 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.784 >>> print(''.join(results), end="")
2025-07-02 04:52:32.784 - abcDefghiJkl
2025-07-02 04:52:32.784 + abcdefGhijkl
2025-07-02 04:52:32.784 """
2025-07-02 04:52:32.784
2025-07-02 04:52:32.784 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.784 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.784 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.784 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.784 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.784
2025-07-02 04:52:32.784 # search for the pair that matches best without being identical
2025-07-02 04:52:32.784 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.784 # on junk -- unless we have to)
2025-07-02 04:52:32.784 for j in range(blo, bhi):
2025-07-02 04:52:32.784 bj = b[j]
2025-07-02 04:52:32.784 cruncher.set_seq2(bj)
2025-07-02 04:52:32.784 for i in range(alo, ahi):
2025-07-02 04:52:32.784 ai = a[i]
2025-07-02 04:52:32.785 if ai == bj:
2025-07-02 04:52:32.785 if eqi is None:
2025-07-02 04:52:32.785 eqi, eqj = i, j
2025-07-02 04:52:32.785 continue
2025-07-02 04:52:32.785 cruncher.set_seq1(ai)
2025-07-02 04:52:32.785 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.785 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.785 # compares by a factor of 3.
2025-07-02 04:52:32.785 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.785 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.785 # of the computation is cached by cruncher
2025-07-02 04:52:32.785 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.785 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.785 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.785 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.785 if best_ratio < cutoff:
2025-07-02 04:52:32.785 # no non-identical "pretty close" pair
2025-07-02 04:52:32.785 if eqi is None:
2025-07-02 04:52:32.785 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.785 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.786 return
2025-07-02 04:52:32.786 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.786 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.786 else:
2025-07-02 04:52:32.786 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.786 eqi = None
2025-07-02 04:52:32.786
2025-07-02 04:52:32.786 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.786 # identical
2025-07-02 04:52:32.786
2025-07-02 04:52:32.786 # pump out diffs from before the synch point
2025-07-02 04:52:32.786 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.786
2025-07-02 04:52:32.786 # do intraline marking on the synch pair
2025-07-02 04:52:32.786 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.786 if eqi is None:
2025-07-02 04:52:32.786 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.786 atags = btags = ""
2025-07-02 04:52:32.786 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.786 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.786 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.787 if tag == 'replace':
2025-07-02 04:52:32.787 atags += '^' * la
2025-07-02 04:52:32.787 btags += '^' * lb
2025-07-02 04:52:32.787 elif tag == 'delete':
2025-07-02 04:52:32.787 atags += '-' * la
2025-07-02 04:52:32.787 elif tag == 'insert':
2025-07-02 04:52:32.787 btags += '+' * lb
2025-07-02 04:52:32.787 elif tag == 'equal':
2025-07-02 04:52:32.787 atags += ' ' * la
2025-07-02 04:52:32.787 btags += ' ' * lb
2025-07-02 04:52:32.787 else:
2025-07-02 04:52:32.787 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.787 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.787 else:
2025-07-02 04:52:32.787 # the synch pair is identical
2025-07-02 04:52:32.787 yield ' ' + aelt
2025-07-02 04:52:32.787
2025-07-02 04:52:32.787 # pump out diffs from after the synch point
2025-07-02 04:52:32.788 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.788
2025-07-02 04:52:32.788 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.788 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.788
2025-07-02 04:52:32.788 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.788 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.788 alo = 287, ahi = 1101
2025-07-02 04:52:32.788 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.788 blo = 287, bhi = 1101
2025-07-02 04:52:32.788
2025-07-02 04:52:32.788 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.788 g = []
2025-07-02 04:52:32.788 if alo < ahi:
2025-07-02 04:52:32.788 if blo < bhi:
2025-07-02 04:52:32.788 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.788 else:
2025-07-02 04:52:32.788 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.788 elif blo < bhi:
2025-07-02 04:52:32.788 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.789
2025-07-02 04:52:32.789 > yield from g
2025-07-02 04:52:32.789
2025-07-02 04:52:32.789 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.789 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.789
2025-07-02 04:52:32.789 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.789 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.789 alo = 287, ahi = 1101
2025-07-02 04:52:32.789 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.789 blo = 287, bhi = 1101
2025-07-02 04:52:32.789
2025-07-02 04:52:32.789 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.789 r"""
2025-07-02 04:52:32.789 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.789 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.789 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.789 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.789
2025-07-02 04:52:32.789 Example:
2025-07-02 04:52:32.789
2025-07-02 04:52:32.790 >>> d = Differ()
2025-07-02 04:52:32.790 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.790 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.790 >>> print(''.join(results), end="")
2025-07-02 04:52:32.790 - abcDefghiJkl
2025-07-02 04:52:32.790 + abcdefGhijkl
2025-07-02 04:52:32.790 """
2025-07-02 04:52:32.790
2025-07-02 04:52:32.790 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.790 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.790 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.790 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.790 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.790
2025-07-02 04:52:32.790 # search for the pair that matches best without being identical
2025-07-02 04:52:32.790 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.790 # on junk -- unless we have to)
2025-07-02 04:52:32.790 for j in range(blo, bhi):
2025-07-02 04:52:32.791 bj = b[j]
2025-07-02 04:52:32.791 cruncher.set_seq2(bj)
2025-07-02 04:52:32.791 for i in range(alo, ahi):
2025-07-02 04:52:32.791 ai = a[i]
2025-07-02 04:52:32.791 if ai == bj:
2025-07-02 04:52:32.791 if eqi is None:
2025-07-02 04:52:32.791 eqi, eqj = i, j
2025-07-02 04:52:32.791 continue
2025-07-02 04:52:32.791 cruncher.set_seq1(ai)
2025-07-02 04:52:32.791 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.791 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.791 # compares by a factor of 3.
2025-07-02 04:52:32.791 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.791 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.791 # of the computation is cached by cruncher
2025-07-02 04:52:32.791 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.791 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.791 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.791 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.791 if best_ratio < cutoff:
2025-07-02 04:52:32.792 # no non-identical "pretty close" pair
2025-07-02 04:52:32.792 if eqi is None:
2025-07-02 04:52:32.792 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.792 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.792 return
2025-07-02 04:52:32.792 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.792 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.792 else:
2025-07-02 04:52:32.792 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.792 eqi = None
2025-07-02 04:52:32.792
2025-07-02 04:52:32.792 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.792 # identical
2025-07-02 04:52:32.792
2025-07-02 04:52:32.792 # pump out diffs from before the synch point
2025-07-02 04:52:32.792 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.792
2025-07-02 04:52:32.792 # do intraline marking on the synch pair
2025-07-02 04:52:32.792 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.792 if eqi is None:
2025-07-02 04:52:32.792 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.793 atags = btags = ""
2025-07-02 04:52:32.793 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.793 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.793 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.793 if tag == 'replace':
2025-07-02 04:52:32.793 atags += '^' * la
2025-07-02 04:52:32.793 btags += '^' * lb
2025-07-02 04:52:32.793 elif tag == 'delete':
2025-07-02 04:52:32.793 atags += '-' * la
2025-07-02 04:52:32.793 elif tag == 'insert':
2025-07-02 04:52:32.793 btags += '+' * lb
2025-07-02 04:52:32.793 elif tag == 'equal':
2025-07-02 04:52:32.793 atags += ' ' * la
2025-07-02 04:52:32.793 btags += ' ' * lb
2025-07-02 04:52:32.793 else:
2025-07-02 04:52:32.793 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.793 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.793 else:
2025-07-02 04:52:32.793 # the synch pair is identical
2025-07-02 04:52:32.793 yield ' ' + aelt
2025-07-02 04:52:32.794
2025-07-02 04:52:32.794 # pump out diffs from after the synch point
2025-07-02 04:52:32.794 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.794
2025-07-02 04:52:32.794 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.794 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.794
2025-07-02 04:52:32.794 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.794 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.794 alo = 290, ahi = 1101
2025-07-02 04:52:32.794 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.794 blo = 290, bhi = 1101
2025-07-02 04:52:32.794
2025-07-02 04:52:32.794 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.794 g = []
2025-07-02 04:52:32.794 if alo < ahi:
2025-07-02 04:52:32.794 if blo < bhi:
2025-07-02 04:52:32.794 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.794 else:
2025-07-02 04:52:32.794 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.795 elif blo < bhi:
2025-07-02 04:52:32.795 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.795
2025-07-02 04:52:32.795 > yield from g
2025-07-02 04:52:32.795
2025-07-02 04:52:32.795 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.795 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.795
2025-07-02 04:52:32.795 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.795 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.795 alo = 290, ahi = 1101
2025-07-02 04:52:32.795 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.795 blo = 290, bhi = 1101
2025-07-02 04:52:32.795
2025-07-02 04:52:32.795 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.795 r"""
2025-07-02 04:52:32.795 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.795 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.795 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.795 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.796
2025-07-02 04:52:32.796 Example:
2025-07-02 04:52:32.796
2025-07-02 04:52:32.796 >>> d = Differ()
2025-07-02 04:52:32.796 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.796 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.796 >>> print(''.join(results), end="")
2025-07-02 04:52:32.796 - abcDefghiJkl
2025-07-02 04:52:32.796 + abcdefGhijkl
2025-07-02 04:52:32.796 """
2025-07-02 04:52:32.796
2025-07-02 04:52:32.796 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.796 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.796 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.796 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.796 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.796
2025-07-02 04:52:32.797 # search for the pair that matches best without being identical
2025-07-02 04:52:32.797 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.797 # on junk -- unless we have to)
2025-07-02 04:52:32.797 for j in range(blo, bhi):
2025-07-02 04:52:32.797 bj = b[j]
2025-07-02 04:52:32.797 cruncher.set_seq2(bj)
2025-07-02 04:52:32.797 for i in range(alo, ahi):
2025-07-02 04:52:32.797 ai = a[i]
2025-07-02 04:52:32.797 if ai == bj:
2025-07-02 04:52:32.797 if eqi is None:
2025-07-02 04:52:32.797 eqi, eqj = i, j
2025-07-02 04:52:32.797 continue
2025-07-02 04:52:32.797 cruncher.set_seq1(ai)
2025-07-02 04:52:32.797 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.797 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.797 # compares by a factor of 3.
2025-07-02 04:52:32.797 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.797 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.797 # of the computation is cached by cruncher
2025-07-02 04:52:32.797 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.798 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.798 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.798 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.798 if best_ratio < cutoff:
2025-07-02 04:52:32.798 # no non-identical "pretty close" pair
2025-07-02 04:52:32.798 if eqi is None:
2025-07-02 04:52:32.798 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.798 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.798 return
2025-07-02 04:52:32.798 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.798 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.798 else:
2025-07-02 04:52:32.798 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.798 eqi = None
2025-07-02 04:52:32.798
2025-07-02 04:52:32.798 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.798 # identical
2025-07-02 04:52:32.798
2025-07-02 04:52:32.798 # pump out diffs from before the synch point
2025-07-02 04:52:32.799 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.799
2025-07-02 04:52:32.799 # do intraline marking on the synch pair
2025-07-02 04:52:32.799 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.799 if eqi is None:
2025-07-02 04:52:32.799 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.799 atags = btags = ""
2025-07-02 04:52:32.799 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.799 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.799 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.799 if tag == 'replace':
2025-07-02 04:52:32.799 atags += '^' * la
2025-07-02 04:52:32.799 btags += '^' * lb
2025-07-02 04:52:32.799 elif tag == 'delete':
2025-07-02 04:52:32.799 atags += '-' * la
2025-07-02 04:52:32.799 elif tag == 'insert':
2025-07-02 04:52:32.799 btags += '+' * lb
2025-07-02 04:52:32.799 elif tag == 'equal':
2025-07-02 04:52:32.799 atags += ' ' * la
2025-07-02 04:52:32.799 btags += ' ' * lb
2025-07-02 04:52:32.800 else:
2025-07-02 04:52:32.800 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.800 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.800 else:
2025-07-02 04:52:32.800 # the synch pair is identical
2025-07-02 04:52:32.800 yield ' ' + aelt
2025-07-02 04:52:32.800
2025-07-02 04:52:32.800 # pump out diffs from after the synch point
2025-07-02 04:52:32.800 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.800
2025-07-02 04:52:32.800 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.800 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.800
2025-07-02 04:52:32.800 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.800 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.800 alo = 291, ahi = 1101
2025-07-02 04:52:32.800 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.800 blo = 291, bhi = 1101
2025-07-02 04:52:32.800
2025-07-02 04:52:32.800 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.800 g = []
2025-07-02 04:52:32.801 if alo < ahi:
2025-07-02 04:52:32.801 if blo < bhi:
2025-07-02 04:52:32.801 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.801 else:
2025-07-02 04:52:32.801 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.801 elif blo < bhi:
2025-07-02 04:52:32.801 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.801
2025-07-02 04:52:32.801 > yield from g
2025-07-02 04:52:32.801
2025-07-02 04:52:32.801 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.801 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.801
2025-07-02 04:52:32.801 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.801 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.801 alo = 291, ahi = 1101
2025-07-02 04:52:32.801 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.801 blo = 291, bhi = 1101
2025-07-02 04:52:32.801
2025-07-02 04:52:32.801 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.801 r"""
2025-07-02 04:52:32.802 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.802 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.802 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.802 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.802
2025-07-02 04:52:32.802 Example:
2025-07-02 04:52:32.802
2025-07-02 04:52:32.802 >>> d = Differ()
2025-07-02 04:52:32.802 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.802 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.802 >>> print(''.join(results), end="")
2025-07-02 04:52:32.802 - abcDefghiJkl
2025-07-02 04:52:32.802 + abcdefGhijkl
2025-07-02 04:52:32.802 """
2025-07-02 04:52:32.802
2025-07-02 04:52:32.802 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.802 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.802 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.802 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.802 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.803
2025-07-02 04:52:32.803 # search for the pair that matches best without being identical
2025-07-02 04:52:32.803 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.803 # on junk -- unless we have to)
2025-07-02 04:52:32.803 for j in range(blo, bhi):
2025-07-02 04:52:32.803 bj = b[j]
2025-07-02 04:52:32.803 cruncher.set_seq2(bj)
2025-07-02 04:52:32.803 for i in range(alo, ahi):
2025-07-02 04:52:32.803 ai = a[i]
2025-07-02 04:52:32.803 if ai == bj:
2025-07-02 04:52:32.803 if eqi is None:
2025-07-02 04:52:32.803 eqi, eqj = i, j
2025-07-02 04:52:32.803 continue
2025-07-02 04:52:32.803 cruncher.set_seq1(ai)
2025-07-02 04:52:32.803 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.803 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.803 # compares by a factor of 3.
2025-07-02 04:52:32.803 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.803 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.803 # of the computation is cached by cruncher
2025-07-02 04:52:32.803 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.804 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.804 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.804 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.804 if best_ratio < cutoff:
2025-07-02 04:52:32.804 # no non-identical "pretty close" pair
2025-07-02 04:52:32.804 if eqi is None:
2025-07-02 04:52:32.804 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.804 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.804 return
2025-07-02 04:52:32.804 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.804 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.804 else:
2025-07-02 04:52:32.804 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.804 eqi = None
2025-07-02 04:52:32.804
2025-07-02 04:52:32.804 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.804 # identical
2025-07-02 04:52:32.804
2025-07-02 04:52:32.804 # pump out diffs from before the synch point
2025-07-02 04:52:32.805 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.805
2025-07-02 04:52:32.805 # do intraline marking on the synch pair
2025-07-02 04:52:32.805 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.805 if eqi is None:
2025-07-02 04:52:32.805 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.805 atags = btags = ""
2025-07-02 04:52:32.805 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.805 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.805 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.805 if tag == 'replace':
2025-07-02 04:52:32.805 atags += '^' * la
2025-07-02 04:52:32.805 btags += '^' * lb
2025-07-02 04:52:32.805 elif tag == 'delete':
2025-07-02 04:52:32.805 atags += '-' * la
2025-07-02 04:52:32.805 elif tag == 'insert':
2025-07-02 04:52:32.805 btags += '+' * lb
2025-07-02 04:52:32.805 elif tag == 'equal':
2025-07-02 04:52:32.805 atags += ' ' * la
2025-07-02 04:52:32.805 btags += ' ' * lb
2025-07-02 04:52:32.806 else:
2025-07-02 04:52:32.806 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.806 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.806 else:
2025-07-02 04:52:32.806 # the synch pair is identical
2025-07-02 04:52:32.806 yield ' ' + aelt
2025-07-02 04:52:32.806
2025-07-02 04:52:32.806 # pump out diffs from after the synch point
2025-07-02 04:52:32.806 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.806
2025-07-02 04:52:32.806 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.806 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.806
2025-07-02 04:52:32.806 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.806 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.806 alo = 292, ahi = 1101
2025-07-02 04:52:32.806 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.806 blo = 292, bhi = 1101
2025-07-02 04:52:32.806
2025-07-02 04:52:32.806 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.806 g = []
2025-07-02 04:52:32.807 if alo < ahi:
2025-07-02 04:52:32.807 if blo < bhi:
2025-07-02 04:52:32.807 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.807 else:
2025-07-02 04:52:32.807 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.807 elif blo < bhi:
2025-07-02 04:52:32.807 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.807
2025-07-02 04:52:32.807 > yield from g
2025-07-02 04:52:32.807
2025-07-02 04:52:32.807 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.807 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.807
2025-07-02 04:52:32.807 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.807 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.807 alo = 292, ahi = 1101
2025-07-02 04:52:32.807 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.807 blo = 292, bhi = 1101
2025-07-02 04:52:32.807
2025-07-02 04:52:32.807 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.808 r"""
2025-07-02 04:52:32.808 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.808 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.808 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.808 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.808
2025-07-02 04:52:32.808 Example:
2025-07-02 04:52:32.808
2025-07-02 04:52:32.808 >>> d = Differ()
2025-07-02 04:52:32.808 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.808 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.808 >>> print(''.join(results), end="")
2025-07-02 04:52:32.808 - abcDefghiJkl
2025-07-02 04:52:32.808 + abcdefGhijkl
2025-07-02 04:52:32.808 """
2025-07-02 04:52:32.808
2025-07-02 04:52:32.808 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.808 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.808 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.809 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.809 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.809
2025-07-02 04:52:32.809 # search for the pair that matches best without being identical
2025-07-02 04:52:32.809 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.809 # on junk -- unless we have to)
2025-07-02 04:52:32.809 for j in range(blo, bhi):
2025-07-02 04:52:32.809 bj = b[j]
2025-07-02 04:52:32.809 cruncher.set_seq2(bj)
2025-07-02 04:52:32.809 for i in range(alo, ahi):
2025-07-02 04:52:32.809 ai = a[i]
2025-07-02 04:52:32.809 if ai == bj:
2025-07-02 04:52:32.809 if eqi is None:
2025-07-02 04:52:32.809 eqi, eqj = i, j
2025-07-02 04:52:32.809 continue
2025-07-02 04:52:32.809 cruncher.set_seq1(ai)
2025-07-02 04:52:32.809 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.809 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.809 # compares by a factor of 3.
2025-07-02 04:52:32.809 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.809 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.810 # of the computation is cached by cruncher
2025-07-02 04:52:32.810 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.810 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.810 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.810 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.810 if best_ratio < cutoff:
2025-07-02 04:52:32.810 # no non-identical "pretty close" pair
2025-07-02 04:52:32.810 if eqi is None:
2025-07-02 04:52:32.810 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.810 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.810 return
2025-07-02 04:52:32.810 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.810 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.810 else:
2025-07-02 04:52:32.810 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.810 eqi = None
2025-07-02 04:52:32.810
2025-07-02 04:52:32.810 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.810 # identical
2025-07-02 04:52:32.810
2025-07-02 04:52:32.811 # pump out diffs from before the synch point
2025-07-02 04:52:32.811 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.811
2025-07-02 04:52:32.811 # do intraline marking on the synch pair
2025-07-02 04:52:32.811 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.811 if eqi is None:
2025-07-02 04:52:32.811 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.811 atags = btags = ""
2025-07-02 04:52:32.811 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.811 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.811 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.811 if tag == 'replace':
2025-07-02 04:52:32.811 atags += '^' * la
2025-07-02 04:52:32.811 btags += '^' * lb
2025-07-02 04:52:32.811 elif tag == 'delete':
2025-07-02 04:52:32.811 atags += '-' * la
2025-07-02 04:52:32.811 elif tag == 'insert':
2025-07-02 04:52:32.811 btags += '+' * lb
2025-07-02 04:52:32.811 elif tag == 'equal':
2025-07-02 04:52:32.811 atags += ' ' * la
2025-07-02 04:52:32.811 btags += ' ' * lb
2025-07-02 04:52:32.812 else:
2025-07-02 04:52:32.812 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.812 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.812 else:
2025-07-02 04:52:32.812 # the synch pair is identical
2025-07-02 04:52:32.812 yield ' ' + aelt
2025-07-02 04:52:32.812
2025-07-02 04:52:32.812 # pump out diffs from after the synch point
2025-07-02 04:52:32.812 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.812
2025-07-02 04:52:32.812 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.812 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.812
2025-07-02 04:52:32.812 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.812 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.812 alo = 293, ahi = 1101
2025-07-02 04:52:32.812 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.812 blo = 293, bhi = 1101
2025-07-02 04:52:32.812
2025-07-02 04:52:32.812 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.812 g = []
2025-07-02 04:52:32.813 if alo < ahi:
2025-07-02 04:52:32.813 if blo < bhi:
2025-07-02 04:52:32.813 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.813 else:
2025-07-02 04:52:32.813 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.813 elif blo < bhi:
2025-07-02 04:52:32.813 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.813
2025-07-02 04:52:32.813 > yield from g
2025-07-02 04:52:32.813
2025-07-02 04:52:32.813 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.813 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.813
2025-07-02 04:52:32.813 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.813 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.813 alo = 293, ahi = 1101
2025-07-02 04:52:32.813 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.813 blo = 293, bhi = 1101
2025-07-02 04:52:32.813
2025-07-02 04:52:32.814 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.814 r"""
2025-07-02 04:52:32.814 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.814 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.814 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.814 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.814
2025-07-02 04:52:32.814 Example:
2025-07-02 04:52:32.814
2025-07-02 04:52:32.814 >>> d = Differ()
2025-07-02 04:52:32.814 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.814 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.814 >>> print(''.join(results), end="")
2025-07-02 04:52:32.814 - abcDefghiJkl
2025-07-02 04:52:32.814 + abcdefGhijkl
2025-07-02 04:52:32.814 """
2025-07-02 04:52:32.814
2025-07-02 04:52:32.814 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.815 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.815 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.815 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.815 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.815
2025-07-02 04:52:32.815 # search for the pair that matches best without being identical
2025-07-02 04:52:32.815 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.815 # on junk -- unless we have to)
2025-07-02 04:52:32.815 for j in range(blo, bhi):
2025-07-02 04:52:32.815 bj = b[j]
2025-07-02 04:52:32.815 cruncher.set_seq2(bj)
2025-07-02 04:52:32.815 for i in range(alo, ahi):
2025-07-02 04:52:32.815 ai = a[i]
2025-07-02 04:52:32.815 if ai == bj:
2025-07-02 04:52:32.815 if eqi is None:
2025-07-02 04:52:32.815 eqi, eqj = i, j
2025-07-02 04:52:32.815 continue
2025-07-02 04:52:32.815 cruncher.set_seq1(ai)
2025-07-02 04:52:32.815 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.815 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.815 # compares by a factor of 3.
2025-07-02 04:52:32.816 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.816 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.816 # of the computation is cached by cruncher
2025-07-02 04:52:32.816 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.816 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.816 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.816 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.816 if best_ratio < cutoff:
2025-07-02 04:52:32.816 # no non-identical "pretty close" pair
2025-07-02 04:52:32.816 if eqi is None:
2025-07-02 04:52:32.816 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.816 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.816 return
2025-07-02 04:52:32.816 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.816 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.816 else:
2025-07-02 04:52:32.816 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.816 eqi = None
2025-07-02 04:52:32.816
2025-07-02 04:52:32.816 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.816 # identical
2025-07-02 04:52:32.817
2025-07-02 04:52:32.817 # pump out diffs from before the synch point
2025-07-02 04:52:32.817 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.817
2025-07-02 04:52:32.817 # do intraline marking on the synch pair
2025-07-02 04:52:32.817 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.817 if eqi is None:
2025-07-02 04:52:32.817 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.817 atags = btags = ""
2025-07-02 04:52:32.817 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.817 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.817 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.817 if tag == 'replace':
2025-07-02 04:52:32.817 atags += '^' * la
2025-07-02 04:52:32.817 btags += '^' * lb
2025-07-02 04:52:32.817 elif tag == 'delete':
2025-07-02 04:52:32.817 atags += '-' * la
2025-07-02 04:52:32.817 elif tag == 'insert':
2025-07-02 04:52:32.817 btags += '+' * lb
2025-07-02 04:52:32.817 elif tag == 'equal':
2025-07-02 04:52:32.817 atags += ' ' * la
2025-07-02 04:52:32.817 btags += ' ' * lb
2025-07-02 04:52:32.818 else:
2025-07-02 04:52:32.818 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.818 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.818 else:
2025-07-02 04:52:32.818 # the synch pair is identical
2025-07-02 04:52:32.818 yield ' ' + aelt
2025-07-02 04:52:32.818
2025-07-02 04:52:32.818 # pump out diffs from after the synch point
2025-07-02 04:52:32.818 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.818
2025-07-02 04:52:32.818 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.818 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.818
2025-07-02 04:52:32.818 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.818 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.818 alo = 294, ahi = 1101
2025-07-02 04:52:32.818 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.818 blo = 294, bhi = 1101
2025-07-02 04:52:32.818
2025-07-02 04:52:32.818 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.818 g = []
2025-07-02 04:52:32.819 if alo < ahi:
2025-07-02 04:52:32.819 if blo < bhi:
2025-07-02 04:52:32.819 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.819 else:
2025-07-02 04:52:32.819 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.819 elif blo < bhi:
2025-07-02 04:52:32.819 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.819
2025-07-02 04:52:32.819 > yield from g
2025-07-02 04:52:32.819
2025-07-02 04:52:32.819 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.819 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.819
2025-07-02 04:52:32.819 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.819 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.819 alo = 294, ahi = 1101
2025-07-02 04:52:32.819 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.819 blo = 294, bhi = 1101
2025-07-02 04:52:32.819
2025-07-02 04:52:32.819 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.819 r"""
2025-07-02 04:52:32.820 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.820 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.820 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.820 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.820
2025-07-02 04:52:32.820 Example:
2025-07-02 04:52:32.820
2025-07-02 04:52:32.820 >>> d = Differ()
2025-07-02 04:52:32.820 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.820 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.820 >>> print(''.join(results), end="")
2025-07-02 04:52:32.820 - abcDefghiJkl
2025-07-02 04:52:32.820 + abcdefGhijkl
2025-07-02 04:52:32.820 """
2025-07-02 04:52:32.820
2025-07-02 04:52:32.820 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.820 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.820 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.820 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.820 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.821
2025-07-02 04:52:32.821 # search for the pair that matches best without being identical
2025-07-02 04:52:32.821 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.821 # on junk -- unless we have to)
2025-07-02 04:52:32.821 for j in range(blo, bhi):
2025-07-02 04:52:32.821 bj = b[j]
2025-07-02 04:52:32.821 cruncher.set_seq2(bj)
2025-07-02 04:52:32.821 for i in range(alo, ahi):
2025-07-02 04:52:32.821 ai = a[i]
2025-07-02 04:52:32.821 if ai == bj:
2025-07-02 04:52:32.821 if eqi is None:
2025-07-02 04:52:32.821 eqi, eqj = i, j
2025-07-02 04:52:32.821 continue
2025-07-02 04:52:32.821 cruncher.set_seq1(ai)
2025-07-02 04:52:32.821 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.821 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.821 # compares by a factor of 3.
2025-07-02 04:52:32.821 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.821 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.821 # of the computation is cached by cruncher
2025-07-02 04:52:32.822 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.822 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.822 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.822 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.822 if best_ratio < cutoff:
2025-07-02 04:52:32.822 # no non-identical "pretty close" pair
2025-07-02 04:52:32.822 if eqi is None:
2025-07-02 04:52:32.822 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.822 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.822 return
2025-07-02 04:52:32.822 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.822 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.822 else:
2025-07-02 04:52:32.822 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.822 eqi = None
2025-07-02 04:52:32.822
2025-07-02 04:52:32.822 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.822 # identical
2025-07-02 04:52:32.822
2025-07-02 04:52:32.822 # pump out diffs from before the synch point
2025-07-02 04:52:32.823 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.823
2025-07-02 04:52:32.823 # do intraline marking on the synch pair
2025-07-02 04:52:32.823 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.823 if eqi is None:
2025-07-02 04:52:32.823 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.823 atags = btags = ""
2025-07-02 04:52:32.823 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.823 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.823 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.823 if tag == 'replace':
2025-07-02 04:52:32.823 atags += '^' * la
2025-07-02 04:52:32.823 btags += '^' * lb
2025-07-02 04:52:32.823 elif tag == 'delete':
2025-07-02 04:52:32.823 atags += '-' * la
2025-07-02 04:52:32.823 elif tag == 'insert':
2025-07-02 04:52:32.823 btags += '+' * lb
2025-07-02 04:52:32.823 elif tag == 'equal':
2025-07-02 04:52:32.823 atags += ' ' * la
2025-07-02 04:52:32.823 btags += ' ' * lb
2025-07-02 04:52:32.823 else:
2025-07-02 04:52:32.823 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.824 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.824 else:
2025-07-02 04:52:32.824 # the synch pair is identical
2025-07-02 04:52:32.824 yield ' ' + aelt
2025-07-02 04:52:32.824
2025-07-02 04:52:32.824 # pump out diffs from after the synch point
2025-07-02 04:52:32.824 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.824
2025-07-02 04:52:32.824 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.824 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.824
2025-07-02 04:52:32.824 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.824 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.824 alo = 295, ahi = 1101
2025-07-02 04:52:32.824 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.824 blo = 295, bhi = 1101
2025-07-02 04:52:32.824
2025-07-02 04:52:32.824 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.824 g = []
2025-07-02 04:52:32.824 if alo < ahi:
2025-07-02 04:52:32.824 if blo < bhi:
2025-07-02 04:52:32.825 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.825 else:
2025-07-02 04:52:32.825 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.825 elif blo < bhi:
2025-07-02 04:52:32.825 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.825
2025-07-02 04:52:32.825 > yield from g
2025-07-02 04:52:32.825
2025-07-02 04:52:32.825 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.825 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.825
2025-07-02 04:52:32.825 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.825 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.825 alo = 295, ahi = 1101
2025-07-02 04:52:32.825 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.825 blo = 295, bhi = 1101
2025-07-02 04:52:32.825
2025-07-02 04:52:32.825 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.825 r"""
2025-07-02 04:52:32.825 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.825 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.826 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.826 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.826
2025-07-02 04:52:32.826 Example:
2025-07-02 04:52:32.826
2025-07-02 04:52:32.826 >>> d = Differ()
2025-07-02 04:52:32.826 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.826 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.826 >>> print(''.join(results), end="")
2025-07-02 04:52:32.826 - abcDefghiJkl
2025-07-02 04:52:32.826 + abcdefGhijkl
2025-07-02 04:52:32.826 """
2025-07-02 04:52:32.826
2025-07-02 04:52:32.826 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.826 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.826 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.826 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.826 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.826
2025-07-02 04:52:32.826 # search for the pair that matches best without being identical
2025-07-02 04:52:32.827 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.827 # on junk -- unless we have to)
2025-07-02 04:52:32.827 for j in range(blo, bhi):
2025-07-02 04:52:32.827 bj = b[j]
2025-07-02 04:52:32.827 cruncher.set_seq2(bj)
2025-07-02 04:52:32.827 for i in range(alo, ahi):
2025-07-02 04:52:32.827 ai = a[i]
2025-07-02 04:52:32.827 if ai == bj:
2025-07-02 04:52:32.827 if eqi is None:
2025-07-02 04:52:32.827 eqi, eqj = i, j
2025-07-02 04:52:32.827 continue
2025-07-02 04:52:32.827 cruncher.set_seq1(ai)
2025-07-02 04:52:32.827 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.827 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.827 # compares by a factor of 3.
2025-07-02 04:52:32.827 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.827 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.827 # of the computation is cached by cruncher
2025-07-02 04:52:32.827 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.827 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.827 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.828 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.828 if best_ratio < cutoff:
2025-07-02 04:52:32.828 # no non-identical "pretty close" pair
2025-07-02 04:52:32.828 if eqi is None:
2025-07-02 04:52:32.828 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.828 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.828 return
2025-07-02 04:52:32.828 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.828 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.828 else:
2025-07-02 04:52:32.828 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.828 eqi = None
2025-07-02 04:52:32.828
2025-07-02 04:52:32.828 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.828 # identical
2025-07-02 04:52:32.828
2025-07-02 04:52:32.828 # pump out diffs from before the synch point
2025-07-02 04:52:32.828 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.828
2025-07-02 04:52:32.828 # do intraline marking on the synch pair
2025-07-02 04:52:32.829 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.829 if eqi is None:
2025-07-02 04:52:32.829 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.829 atags = btags = ""
2025-07-02 04:52:32.829 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.829 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.829 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.829 if tag == 'replace':
2025-07-02 04:52:32.829 atags += '^' * la
2025-07-02 04:52:32.829 btags += '^' * lb
2025-07-02 04:52:32.829 elif tag == 'delete':
2025-07-02 04:52:32.829 atags += '-' * la
2025-07-02 04:52:32.829 elif tag == 'insert':
2025-07-02 04:52:32.829 btags += '+' * lb
2025-07-02 04:52:32.829 elif tag == 'equal':
2025-07-02 04:52:32.829 atags += ' ' * la
2025-07-02 04:52:32.829 btags += ' ' * lb
2025-07-02 04:52:32.829 else:
2025-07-02 04:52:32.829 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.829 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.830 else:
2025-07-02 04:52:32.830 # the synch pair is identical
2025-07-02 04:52:32.830 yield ' ' + aelt
2025-07-02 04:52:32.830
2025-07-02 04:52:32.830 # pump out diffs from after the synch point
2025-07-02 04:52:32.830 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.830
2025-07-02 04:52:32.830 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.830 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.830
2025-07-02 04:52:32.830 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.830 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.830 alo = 296, ahi = 1101
2025-07-02 04:52:32.830 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.830 blo = 296, bhi = 1101
2025-07-02 04:52:32.830
2025-07-02 04:52:32.830 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.830 g = []
2025-07-02 04:52:32.830 if alo < ahi:
2025-07-02 04:52:32.830 if blo < bhi:
2025-07-02 04:52:32.830 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.831 else:
2025-07-02 04:52:32.831 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.831 elif blo < bhi:
2025-07-02 04:52:32.831 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.831
2025-07-02 04:52:32.831 > yield from g
2025-07-02 04:52:32.831
2025-07-02 04:52:32.831 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.831 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.831
2025-07-02 04:52:32.831 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.831 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.831 alo = 296, ahi = 1101
2025-07-02 04:52:32.831 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.831 blo = 296, bhi = 1101
2025-07-02 04:52:32.831
2025-07-02 04:52:32.831 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.831 r"""
2025-07-02 04:52:32.831 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.831 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.832 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.832 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.832
2025-07-02 04:52:32.832 Example:
2025-07-02 04:52:32.832
2025-07-02 04:52:32.832 >>> d = Differ()
2025-07-02 04:52:32.832 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.832 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.832 >>> print(''.join(results), end="")
2025-07-02 04:52:32.832 - abcDefghiJkl
2025-07-02 04:52:32.832 + abcdefGhijkl
2025-07-02 04:52:32.832 """
2025-07-02 04:52:32.832
2025-07-02 04:52:32.832 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.832 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.832 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.832 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.832 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.832
2025-07-02 04:52:32.832 # search for the pair that matches best without being identical
2025-07-02 04:52:32.833 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.833 # on junk -- unless we have to)
2025-07-02 04:52:32.833 for j in range(blo, bhi):
2025-07-02 04:52:32.833 bj = b[j]
2025-07-02 04:52:32.833 cruncher.set_seq2(bj)
2025-07-02 04:52:32.833 for i in range(alo, ahi):
2025-07-02 04:52:32.833 ai = a[i]
2025-07-02 04:52:32.833 if ai == bj:
2025-07-02 04:52:32.833 if eqi is None:
2025-07-02 04:52:32.833 eqi, eqj = i, j
2025-07-02 04:52:32.833 continue
2025-07-02 04:52:32.833 cruncher.set_seq1(ai)
2025-07-02 04:52:32.833 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.833 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.833 # compares by a factor of 3.
2025-07-02 04:52:32.833 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.833 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.833 # of the computation is cached by cruncher
2025-07-02 04:52:32.833 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.833 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.833 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.834 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.834 if best_ratio < cutoff:
2025-07-02 04:52:32.834 # no non-identical "pretty close" pair
2025-07-02 04:52:32.834 if eqi is None:
2025-07-02 04:52:32.834 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.834 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.834 return
2025-07-02 04:52:32.834 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.834 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.834 else:
2025-07-02 04:52:32.834 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.834 eqi = None
2025-07-02 04:52:32.834
2025-07-02 04:52:32.834 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.834 # identical
2025-07-02 04:52:32.834
2025-07-02 04:52:32.834 # pump out diffs from before the synch point
2025-07-02 04:52:32.834 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.834
2025-07-02 04:52:32.834 # do intraline marking on the synch pair
2025-07-02 04:52:32.834 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.834 if eqi is None:
2025-07-02 04:52:32.835 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.835 atags = btags = ""
2025-07-02 04:52:32.835 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.835 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.835 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.835 if tag == 'replace':
2025-07-02 04:52:32.835 atags += '^' * la
2025-07-02 04:52:32.835 btags += '^' * lb
2025-07-02 04:52:32.835 elif tag == 'delete':
2025-07-02 04:52:32.835 atags += '-' * la
2025-07-02 04:52:32.835 elif tag == 'insert':
2025-07-02 04:52:32.835 btags += '+' * lb
2025-07-02 04:52:32.835 elif tag == 'equal':
2025-07-02 04:52:32.835 atags += ' ' * la
2025-07-02 04:52:32.835 btags += ' ' * lb
2025-07-02 04:52:32.835 else:
2025-07-02 04:52:32.835 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.835 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.835 else:
2025-07-02 04:52:32.835 # the synch pair is identical
2025-07-02 04:52:32.835 yield ' ' + aelt
2025-07-02 04:52:32.836
2025-07-02 04:52:32.836 # pump out diffs from after the synch point
2025-07-02 04:52:32.836 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.836
2025-07-02 04:52:32.836 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.836 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.836
2025-07-02 04:52:32.836 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.836 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.836 alo = 297, ahi = 1101
2025-07-02 04:52:32.836 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.836 blo = 297, bhi = 1101
2025-07-02 04:52:32.836
2025-07-02 04:52:32.836 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.836 g = []
2025-07-02 04:52:32.836 if alo < ahi:
2025-07-02 04:52:32.836 if blo < bhi:
2025-07-02 04:52:32.836 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.836 else:
2025-07-02 04:52:32.836 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.836 elif blo < bhi:
2025-07-02 04:52:32.836 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.837
2025-07-02 04:52:32.837 > yield from g
2025-07-02 04:52:32.837
2025-07-02 04:52:32.837 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.837 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.837
2025-07-02 04:52:32.837 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.837 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.837 alo = 297, ahi = 1101
2025-07-02 04:52:32.837 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.837 blo = 297, bhi = 1101
2025-07-02 04:52:32.837
2025-07-02 04:52:32.837 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.837 r"""
2025-07-02 04:52:32.837 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.837 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.837 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.837 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.837
2025-07-02 04:52:32.837 Example:
2025-07-02 04:52:32.838
2025-07-02 04:52:32.838 >>> d = Differ()
2025-07-02 04:52:32.838 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.838 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.838 >>> print(''.join(results), end="")
2025-07-02 04:52:32.838 - abcDefghiJkl
2025-07-02 04:52:32.838 + abcdefGhijkl
2025-07-02 04:52:32.838 """
2025-07-02 04:52:32.838
2025-07-02 04:52:32.838 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.838 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.838 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.838 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.838 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.838
2025-07-02 04:52:32.838 # search for the pair that matches best without being identical
2025-07-02 04:52:32.838 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.838 # on junk -- unless we have to)
2025-07-02 04:52:32.839 for j in range(blo, bhi):
2025-07-02 04:52:32.839 bj = b[j]
2025-07-02 04:52:32.839 cruncher.set_seq2(bj)
2025-07-02 04:52:32.839 for i in range(alo, ahi):
2025-07-02 04:52:32.839 ai = a[i]
2025-07-02 04:52:32.839 if ai == bj:
2025-07-02 04:52:32.839 if eqi is None:
2025-07-02 04:52:32.839 eqi, eqj = i, j
2025-07-02 04:52:32.839 continue
2025-07-02 04:52:32.839 cruncher.set_seq1(ai)
2025-07-02 04:52:32.839 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.839 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.839 # compares by a factor of 3.
2025-07-02 04:52:32.839 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.839 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.839 # of the computation is cached by cruncher
2025-07-02 04:52:32.839 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.839 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.839 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.839 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.839 if best_ratio < cutoff:
2025-07-02 04:52:32.840 # no non-identical "pretty close" pair
2025-07-02 04:52:32.840 if eqi is None:
2025-07-02 04:52:32.840 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.840 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.840 return
2025-07-02 04:52:32.840 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.840 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.840 else:
2025-07-02 04:52:32.840 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.840 eqi = None
2025-07-02 04:52:32.840
2025-07-02 04:52:32.840 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.840 # identical
2025-07-02 04:52:32.840
2025-07-02 04:52:32.840 # pump out diffs from before the synch point
2025-07-02 04:52:32.840 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.840
2025-07-02 04:52:32.840 # do intraline marking on the synch pair
2025-07-02 04:52:32.840 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.840 if eqi is None:
2025-07-02 04:52:32.840 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.841 atags = btags = ""
2025-07-02 04:52:32.841 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.841 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.841 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.841 if tag == 'replace':
2025-07-02 04:52:32.841 atags += '^' * la
2025-07-02 04:52:32.841 btags += '^' * lb
2025-07-02 04:52:32.841 elif tag == 'delete':
2025-07-02 04:52:32.841 atags += '-' * la
2025-07-02 04:52:32.841 elif tag == 'insert':
2025-07-02 04:52:32.841 btags += '+' * lb
2025-07-02 04:52:32.841 elif tag == 'equal':
2025-07-02 04:52:32.841 atags += ' ' * la
2025-07-02 04:52:32.841 btags += ' ' * lb
2025-07-02 04:52:32.841 else:
2025-07-02 04:52:32.841 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.841 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.841 else:
2025-07-02 04:52:32.841 # the synch pair is identical
2025-07-02 04:52:32.841 yield ' ' + aelt
2025-07-02 04:52:32.841
2025-07-02 04:52:32.841 # pump out diffs from after the synch point
2025-07-02 04:52:32.842 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.842
2025-07-02 04:52:32.842 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.842 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.842
2025-07-02 04:52:32.842 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.842 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.842 alo = 298, ahi = 1101
2025-07-02 04:52:32.842 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.842 blo = 298, bhi = 1101
2025-07-02 04:52:32.842
2025-07-02 04:52:32.842 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.842 g = []
2025-07-02 04:52:32.842 if alo < ahi:
2025-07-02 04:52:32.842 if blo < bhi:
2025-07-02 04:52:32.842 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.842 else:
2025-07-02 04:52:32.842 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.842 elif blo < bhi:
2025-07-02 04:52:32.842 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.842
2025-07-02 04:52:32.843 > yield from g
2025-07-02 04:52:32.843
2025-07-02 04:52:32.843 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.843 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.843
2025-07-02 04:52:32.843 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.843 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.843 alo = 298, ahi = 1101
2025-07-02 04:52:32.843 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.843 blo = 298, bhi = 1101
2025-07-02 04:52:32.843
2025-07-02 04:52:32.843 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.843 r"""
2025-07-02 04:52:32.843 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.843 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.843 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.843 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.843
2025-07-02 04:52:32.843 Example:
2025-07-02 04:52:32.843
2025-07-02 04:52:32.844 >>> d = Differ()
2025-07-02 04:52:32.844 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.844 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.844 >>> print(''.join(results), end="")
2025-07-02 04:52:32.844 - abcDefghiJkl
2025-07-02 04:52:32.844 + abcdefGhijkl
2025-07-02 04:52:32.844 """
2025-07-02 04:52:32.844
2025-07-02 04:52:32.844 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.844 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.844 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.844 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.844 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.844
2025-07-02 04:52:32.844 # search for the pair that matches best without being identical
2025-07-02 04:52:32.844 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.844 # on junk -- unless we have to)
2025-07-02 04:52:32.845 for j in range(blo, bhi):
2025-07-02 04:52:32.845 bj = b[j]
2025-07-02 04:52:32.845 cruncher.set_seq2(bj)
2025-07-02 04:52:32.845 for i in range(alo, ahi):
2025-07-02 04:52:32.845 ai = a[i]
2025-07-02 04:52:32.845 if ai == bj:
2025-07-02 04:52:32.845 if eqi is None:
2025-07-02 04:52:32.845 eqi, eqj = i, j
2025-07-02 04:52:32.845 continue
2025-07-02 04:52:32.845 cruncher.set_seq1(ai)
2025-07-02 04:52:32.845 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.845 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.845 # compares by a factor of 3.
2025-07-02 04:52:32.845 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.845 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.845 # of the computation is cached by cruncher
2025-07-02 04:52:32.845 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.845 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.845 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.845 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.845 if best_ratio < cutoff:
2025-07-02 04:52:32.846 # no non-identical "pretty close" pair
2025-07-02 04:52:32.846 if eqi is None:
2025-07-02 04:52:32.846 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.846 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.846 return
2025-07-02 04:52:32.846 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.846 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.846 else:
2025-07-02 04:52:32.846 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.846 eqi = None
2025-07-02 04:52:32.846
2025-07-02 04:52:32.846 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.846 # identical
2025-07-02 04:52:32.846
2025-07-02 04:52:32.846 # pump out diffs from before the synch point
2025-07-02 04:52:32.846 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.846
2025-07-02 04:52:32.846 # do intraline marking on the synch pair
2025-07-02 04:52:32.846 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.847 if eqi is None:
2025-07-02 04:52:32.847 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.847 atags = btags = ""
2025-07-02 04:52:32.847 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.847 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.847 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.847 if tag == 'replace':
2025-07-02 04:52:32.847 atags += '^' * la
2025-07-02 04:52:32.847 btags += '^' * lb
2025-07-02 04:52:32.847 elif tag == 'delete':
2025-07-02 04:52:32.847 atags += '-' * la
2025-07-02 04:52:32.847 elif tag == 'insert':
2025-07-02 04:52:32.847 btags += '+' * lb
2025-07-02 04:52:32.847 elif tag == 'equal':
2025-07-02 04:52:32.847 atags += ' ' * la
2025-07-02 04:52:32.847 btags += ' ' * lb
2025-07-02 04:52:32.847 else:
2025-07-02 04:52:32.847 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.847 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.847 else:
2025-07-02 04:52:32.848 # the synch pair is identical
2025-07-02 04:52:32.848 yield ' ' + aelt
2025-07-02 04:52:32.848
2025-07-02 04:52:32.848 # pump out diffs from after the synch point
2025-07-02 04:52:32.848 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.848
2025-07-02 04:52:32.848 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.848 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.848
2025-07-02 04:52:32.848 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.848 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.848 alo = 299, ahi = 1101
2025-07-02 04:52:32.848 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.848 blo = 299, bhi = 1101
2025-07-02 04:52:32.848
2025-07-02 04:52:32.848 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.848 g = []
2025-07-02 04:52:32.848 if alo < ahi:
2025-07-02 04:52:32.848 if blo < bhi:
2025-07-02 04:52:32.849 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.849 else:
2025-07-02 04:52:32.849 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.849 elif blo < bhi:
2025-07-02 04:52:32.849 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.849
2025-07-02 04:52:32.849 > yield from g
2025-07-02 04:52:32.849
2025-07-02 04:52:32.849 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.849 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.849
2025-07-02 04:52:32.849 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.849 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.849 alo = 299, ahi = 1101
2025-07-02 04:52:32.849 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.849 blo = 299, bhi = 1101
2025-07-02 04:52:32.849
2025-07-02 04:52:32.849 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.849 r"""
2025-07-02 04:52:32.849 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.850 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.850 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.850 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.850
2025-07-02 04:52:32.850 Example:
2025-07-02 04:52:32.850
2025-07-02 04:52:32.850 >>> d = Differ()
2025-07-02 04:52:32.850 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.850 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.850 >>> print(''.join(results), end="")
2025-07-02 04:52:32.850 - abcDefghiJkl
2025-07-02 04:52:32.850 + abcdefGhijkl
2025-07-02 04:52:32.850 """
2025-07-02 04:52:32.850
2025-07-02 04:52:32.850 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.850 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.851 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.851 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.851 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.851
2025-07-02 04:52:32.851 # search for the pair that matches best without being identical
2025-07-02 04:52:32.851 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.851 # on junk -- unless we have to)
2025-07-02 04:52:32.851 for j in range(blo, bhi):
2025-07-02 04:52:32.851 bj = b[j]
2025-07-02 04:52:32.851 cruncher.set_seq2(bj)
2025-07-02 04:52:32.851 for i in range(alo, ahi):
2025-07-02 04:52:32.851 ai = a[i]
2025-07-02 04:52:32.851 if ai == bj:
2025-07-02 04:52:32.851 if eqi is None:
2025-07-02 04:52:32.851 eqi, eqj = i, j
2025-07-02 04:52:32.851 continue
2025-07-02 04:52:32.851 cruncher.set_seq1(ai)
2025-07-02 04:52:32.851 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.851 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.851 # compares by a factor of 3.
2025-07-02 04:52:32.852 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.852 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.852 # of the computation is cached by cruncher
2025-07-02 04:52:32.852 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.852 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.852 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.852 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.852 if best_ratio < cutoff:
2025-07-02 04:52:32.852 # no non-identical "pretty close" pair
2025-07-02 04:52:32.852 if eqi is None:
2025-07-02 04:52:32.852 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.852 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.852 return
2025-07-02 04:52:32.852 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.852 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.852 else:
2025-07-02 04:52:32.852 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.852 eqi = None
2025-07-02 04:52:32.852
2025-07-02 04:52:32.853 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.853 # identical
2025-07-02 04:52:32.853
2025-07-02 04:52:32.853 # pump out diffs from before the synch point
2025-07-02 04:52:32.853 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.853
2025-07-02 04:52:32.853 # do intraline marking on the synch pair
2025-07-02 04:52:32.853 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.853 if eqi is None:
2025-07-02 04:52:32.853 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.853 atags = btags = ""
2025-07-02 04:52:32.853 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.853 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.853 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.853 if tag == 'replace':
2025-07-02 04:52:32.853 atags += '^' * la
2025-07-02 04:52:32.853 btags += '^' * lb
2025-07-02 04:52:32.853 elif tag == 'delete':
2025-07-02 04:52:32.853 atags += '-' * la
2025-07-02 04:52:32.853 elif tag == 'insert':
2025-07-02 04:52:32.854 btags += '+' * lb
2025-07-02 04:52:32.854 elif tag == 'equal':
2025-07-02 04:52:32.854 atags += ' ' * la
2025-07-02 04:52:32.854 btags += ' ' * lb
2025-07-02 04:52:32.854 else:
2025-07-02 04:52:32.854 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.854 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.854 else:
2025-07-02 04:52:32.854 # the synch pair is identical
2025-07-02 04:52:32.854 yield ' ' + aelt
2025-07-02 04:52:32.854
2025-07-02 04:52:32.854 # pump out diffs from after the synch point
2025-07-02 04:52:32.854 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.854
2025-07-02 04:52:32.854 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.854 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.854
2025-07-02 04:52:32.854 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.854 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.854 alo = 300, ahi = 1101
2025-07-02 04:52:32.855 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.855 blo = 300, bhi = 1101
2025-07-02 04:52:32.855
2025-07-02 04:52:32.855 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.855 g = []
2025-07-02 04:52:32.855 if alo < ahi:
2025-07-02 04:52:32.855 if blo < bhi:
2025-07-02 04:52:32.855 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.855 else:
2025-07-02 04:52:32.855 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.855 elif blo < bhi:
2025-07-02 04:52:32.855 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.855
2025-07-02 04:52:32.855 > yield from g
2025-07-02 04:52:32.855
2025-07-02 04:52:32.855 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.855 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.855
2025-07-02 04:52:32.855 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.856 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.856 alo = 300, ahi = 1101
2025-07-02 04:52:32.856 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.856 blo = 300, bhi = 1101
2025-07-02 04:52:32.856
2025-07-02 04:52:32.856 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.856 r"""
2025-07-02 04:52:32.856 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.856 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.856 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.856 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.856
2025-07-02 04:52:32.856 Example:
2025-07-02 04:52:32.856
2025-07-02 04:52:32.856 >>> d = Differ()
2025-07-02 04:52:32.856 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.856 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.856 >>> print(''.join(results), end="")
2025-07-02 04:52:32.856 - abcDefghiJkl
2025-07-02 04:52:32.857 + abcdefGhijkl
2025-07-02 04:52:32.857 """
2025-07-02 04:52:32.857
2025-07-02 04:52:32.857 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.857 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.857 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.857 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.857 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.857
2025-07-02 04:52:32.857 # search for the pair that matches best without being identical
2025-07-02 04:52:32.857 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.857 # on junk -- unless we have to)
2025-07-02 04:52:32.857 for j in range(blo, bhi):
2025-07-02 04:52:32.857 bj = b[j]
2025-07-02 04:52:32.857 cruncher.set_seq2(bj)
2025-07-02 04:52:32.857 for i in range(alo, ahi):
2025-07-02 04:52:32.857 ai = a[i]
2025-07-02 04:52:32.857 if ai == bj:
2025-07-02 04:52:32.857 if eqi is None:
2025-07-02 04:52:32.858 eqi, eqj = i, j
2025-07-02 04:52:32.858 continue
2025-07-02 04:52:32.858 cruncher.set_seq1(ai)
2025-07-02 04:52:32.858 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.858 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.858 # compares by a factor of 3.
2025-07-02 04:52:32.858 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.858 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.858 # of the computation is cached by cruncher
2025-07-02 04:52:32.858 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.858 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.858 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.858 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.858 if best_ratio < cutoff:
2025-07-02 04:52:32.858 # no non-identical "pretty close" pair
2025-07-02 04:52:32.858 if eqi is None:
2025-07-02 04:52:32.858 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.858 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.858 return
2025-07-02 04:52:32.858 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.859 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.859 else:
2025-07-02 04:52:32.859 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.859 eqi = None
2025-07-02 04:52:32.859
2025-07-02 04:52:32.859 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.859 # identical
2025-07-02 04:52:32.859
2025-07-02 04:52:32.859 # pump out diffs from before the synch point
2025-07-02 04:52:32.859 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.859
2025-07-02 04:52:32.859 # do intraline marking on the synch pair
2025-07-02 04:52:32.859 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.859 if eqi is None:
2025-07-02 04:52:32.859 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.859 atags = btags = ""
2025-07-02 04:52:32.859 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.859 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.859 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.859 if tag == 'replace':
2025-07-02 04:52:32.859 atags += '^' * la
2025-07-02 04:52:32.860 btags += '^' * lb
2025-07-02 04:52:32.860 elif tag == 'delete':
2025-07-02 04:52:32.860 atags += '-' * la
2025-07-02 04:52:32.860 elif tag == 'insert':
2025-07-02 04:52:32.860 btags += '+' * lb
2025-07-02 04:52:32.860 elif tag == 'equal':
2025-07-02 04:52:32.860 atags += ' ' * la
2025-07-02 04:52:32.860 btags += ' ' * lb
2025-07-02 04:52:32.860 else:
2025-07-02 04:52:32.860 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.860 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.860 else:
2025-07-02 04:52:32.860 # the synch pair is identical
2025-07-02 04:52:32.860 yield ' ' + aelt
2025-07-02 04:52:32.860
2025-07-02 04:52:32.860 # pump out diffs from after the synch point
2025-07-02 04:52:32.860 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.860
2025-07-02 04:52:32.860 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.861 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.861
2025-07-02 04:52:32.861 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.861 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.861 alo = 301, ahi = 1101
2025-07-02 04:52:32.861 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.861 blo = 301, bhi = 1101
2025-07-02 04:52:32.861
2025-07-02 04:52:32.861 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.861 g = []
2025-07-02 04:52:32.861 if alo < ahi:
2025-07-02 04:52:32.861 if blo < bhi:
2025-07-02 04:52:32.861 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.861 else:
2025-07-02 04:52:32.861 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.861 elif blo < bhi:
2025-07-02 04:52:32.861 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.861
2025-07-02 04:52:32.861 > yield from g
2025-07-02 04:52:32.862
2025-07-02 04:52:32.862 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.862 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.862
2025-07-02 04:52:32.862 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.862 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.862 alo = 301, ahi = 1101
2025-07-02 04:52:32.862 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.862 blo = 301, bhi = 1101
2025-07-02 04:52:32.862
2025-07-02 04:52:32.862 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.862 r"""
2025-07-02 04:52:32.862 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.862 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.862 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.862 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.862
2025-07-02 04:52:32.862 Example:
2025-07-02 04:52:32.862
2025-07-02 04:52:32.862 >>> d = Differ()
2025-07-02 04:52:32.862 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.863 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.863 >>> print(''.join(results), end="")
2025-07-02 04:52:32.863 - abcDefghiJkl
2025-07-02 04:52:32.863 + abcdefGhijkl
2025-07-02 04:52:32.863 """
2025-07-02 04:52:32.863
2025-07-02 04:52:32.863 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.863 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.863 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.863 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.863 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.863
2025-07-02 04:52:32.863 # search for the pair that matches best without being identical
2025-07-02 04:52:32.863 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.863 # on junk -- unless we have to)
2025-07-02 04:52:32.863 for j in range(blo, bhi):
2025-07-02 04:52:32.863 bj = b[j]
2025-07-02 04:52:32.864 cruncher.set_seq2(bj)
2025-07-02 04:52:32.864 for i in range(alo, ahi):
2025-07-02 04:52:32.864 ai = a[i]
2025-07-02 04:52:32.864 if ai == bj:
2025-07-02 04:52:32.864 if eqi is None:
2025-07-02 04:52:32.864 eqi, eqj = i, j
2025-07-02 04:52:32.864 continue
2025-07-02 04:52:32.864 cruncher.set_seq1(ai)
2025-07-02 04:52:32.864 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.864 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.864 # compares by a factor of 3.
2025-07-02 04:52:32.864 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.864 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.864 # of the computation is cached by cruncher
2025-07-02 04:52:32.864 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.864 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.864 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.864 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.864 if best_ratio < cutoff:
2025-07-02 04:52:32.864 # no non-identical "pretty close" pair
2025-07-02 04:52:32.865 if eqi is None:
2025-07-02 04:52:32.865 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.865 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.865 return
2025-07-02 04:52:32.865 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.865 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.865 else:
2025-07-02 04:52:32.865 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.865 eqi = None
2025-07-02 04:52:32.865
2025-07-02 04:52:32.865 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.865 # identical
2025-07-02 04:52:32.865
2025-07-02 04:52:32.865 # pump out diffs from before the synch point
2025-07-02 04:52:32.865 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.865
2025-07-02 04:52:32.865 # do intraline marking on the synch pair
2025-07-02 04:52:32.865 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.865 if eqi is None:
2025-07-02 04:52:32.865 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.866 atags = btags = ""
2025-07-02 04:52:32.866 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.866 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.866 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.866 if tag == 'replace':
2025-07-02 04:52:32.866 atags += '^' * la
2025-07-02 04:52:32.866 btags += '^' * lb
2025-07-02 04:52:32.866 elif tag == 'delete':
2025-07-02 04:52:32.866 atags += '-' * la
2025-07-02 04:52:32.866 elif tag == 'insert':
2025-07-02 04:52:32.866 btags += '+' * lb
2025-07-02 04:52:32.866 elif tag == 'equal':
2025-07-02 04:52:32.866 atags += ' ' * la
2025-07-02 04:52:32.866 btags += ' ' * lb
2025-07-02 04:52:32.866 else:
2025-07-02 04:52:32.866 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.866 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.866 else:
2025-07-02 04:52:32.866 # the synch pair is identical
2025-07-02 04:52:32.866 yield ' ' + aelt
2025-07-02 04:52:32.867
2025-07-02 04:52:32.867 # pump out diffs from after the synch point
2025-07-02 04:52:32.867 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.867
2025-07-02 04:52:32.867 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.867 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.867
2025-07-02 04:52:32.867 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.867 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.867 alo = 302, ahi = 1101
2025-07-02 04:52:32.867 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.867 blo = 302, bhi = 1101
2025-07-02 04:52:32.867
2025-07-02 04:52:32.867 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.867 g = []
2025-07-02 04:52:32.867 if alo < ahi:
2025-07-02 04:52:32.867 if blo < bhi:
2025-07-02 04:52:32.867 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.867 else:
2025-07-02 04:52:32.867 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.867 elif blo < bhi:
2025-07-02 04:52:32.868 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.868
2025-07-02 04:52:32.868 > yield from g
2025-07-02 04:52:32.868
2025-07-02 04:52:32.868 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.868 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.868
2025-07-02 04:52:32.868 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.868 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.868 alo = 302, ahi = 1101
2025-07-02 04:52:32.868 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.868 blo = 302, bhi = 1101
2025-07-02 04:52:32.868
2025-07-02 04:52:32.868 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.868 r"""
2025-07-02 04:52:32.868 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.868 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.868 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.868 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.868
2025-07-02 04:52:32.869 Example:
2025-07-02 04:52:32.869
2025-07-02 04:52:32.869 >>> d = Differ()
2025-07-02 04:52:32.869 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.869 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.869 >>> print(''.join(results), end="")
2025-07-02 04:52:32.869 - abcDefghiJkl
2025-07-02 04:52:32.869 + abcdefGhijkl
2025-07-02 04:52:32.869 """
2025-07-02 04:52:32.869
2025-07-02 04:52:32.869 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.869 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.869 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.869 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.869 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.869
2025-07-02 04:52:32.869 # search for the pair that matches best without being identical
2025-07-02 04:52:32.869 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.869 # on junk -- unless we have to)
2025-07-02 04:52:32.870 for j in range(blo, bhi):
2025-07-02 04:52:32.870 bj = b[j]
2025-07-02 04:52:32.870 cruncher.set_seq2(bj)
2025-07-02 04:52:32.870 for i in range(alo, ahi):
2025-07-02 04:52:32.870 ai = a[i]
2025-07-02 04:52:32.870 if ai == bj:
2025-07-02 04:52:32.870 if eqi is None:
2025-07-02 04:52:32.870 eqi, eqj = i, j
2025-07-02 04:52:32.870 continue
2025-07-02 04:52:32.870 cruncher.set_seq1(ai)
2025-07-02 04:52:32.870 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.870 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.870 # compares by a factor of 3.
2025-07-02 04:52:32.870 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.870 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.870 # of the computation is cached by cruncher
2025-07-02 04:52:32.870 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.870 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.870 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.870 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.871 if best_ratio < cutoff:
2025-07-02 04:52:32.871 # no non-identical "pretty close" pair
2025-07-02 04:52:32.871 if eqi is None:
2025-07-02 04:52:32.871 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.871 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.871 return
2025-07-02 04:52:32.871 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.871 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.871 else:
2025-07-02 04:52:32.871 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.871 eqi = None
2025-07-02 04:52:32.871
2025-07-02 04:52:32.871 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.871 # identical
2025-07-02 04:52:32.871
2025-07-02 04:52:32.871 # pump out diffs from before the synch point
2025-07-02 04:52:32.871 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.871
2025-07-02 04:52:32.871 # do intraline marking on the synch pair
2025-07-02 04:52:32.871 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.871 if eqi is None:
2025-07-02 04:52:32.872 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.872 atags = btags = ""
2025-07-02 04:52:32.872 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.872 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.872 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.872 if tag == 'replace':
2025-07-02 04:52:32.872 atags += '^' * la
2025-07-02 04:52:32.872 btags += '^' * lb
2025-07-02 04:52:32.872 elif tag == 'delete':
2025-07-02 04:52:32.872 atags += '-' * la
2025-07-02 04:52:32.872 elif tag == 'insert':
2025-07-02 04:52:32.872 btags += '+' * lb
2025-07-02 04:52:32.872 elif tag == 'equal':
2025-07-02 04:52:32.872 atags += ' ' * la
2025-07-02 04:52:32.872 btags += ' ' * lb
2025-07-02 04:52:32.872 else:
2025-07-02 04:52:32.872 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.872 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.872 else:
2025-07-02 04:52:32.873 # the synch pair is identical
2025-07-02 04:52:32.873 yield ' ' + aelt
2025-07-02 04:52:32.873
2025-07-02 04:52:32.873 # pump out diffs from after the synch point
2025-07-02 04:52:32.873 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.873
2025-07-02 04:52:32.873 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.873 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.873
2025-07-02 04:52:32.873 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.873 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.873 alo = 303, ahi = 1101
2025-07-02 04:52:32.873 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.873 blo = 303, bhi = 1101
2025-07-02 04:52:32.873
2025-07-02 04:52:32.873 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.873 g = []
2025-07-02 04:52:32.873 if alo < ahi:
2025-07-02 04:52:32.873 if blo < bhi:
2025-07-02 04:52:32.874 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.874 else:
2025-07-02 04:52:32.874 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.874 elif blo < bhi:
2025-07-02 04:52:32.874 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.874
2025-07-02 04:52:32.874 > yield from g
2025-07-02 04:52:32.874
2025-07-02 04:52:32.874 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.874 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.874
2025-07-02 04:52:32.874 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.874 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.874 alo = 303, ahi = 1101
2025-07-02 04:52:32.874 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.874 blo = 303, bhi = 1101
2025-07-02 04:52:32.874
2025-07-02 04:52:32.874 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.874 r"""
2025-07-02 04:52:32.874 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.875 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.875 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.875 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.875
2025-07-02 04:52:32.875 Example:
2025-07-02 04:52:32.875
2025-07-02 04:52:32.875 >>> d = Differ()
2025-07-02 04:52:32.875 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.875 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.875 >>> print(''.join(results), end="")
2025-07-02 04:52:32.875 - abcDefghiJkl
2025-07-02 04:52:32.875 + abcdefGhijkl
2025-07-02 04:52:32.875 """
2025-07-02 04:52:32.875
2025-07-02 04:52:32.875 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.875 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.875 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.875 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.875 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.876
2025-07-02 04:52:32.876 # search for the pair that matches best without being identical
2025-07-02 04:52:32.876 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.876 # on junk -- unless we have to)
2025-07-02 04:52:32.876 for j in range(blo, bhi):
2025-07-02 04:52:32.876 bj = b[j]
2025-07-02 04:52:32.876 cruncher.set_seq2(bj)
2025-07-02 04:52:32.876 for i in range(alo, ahi):
2025-07-02 04:52:32.876 ai = a[i]
2025-07-02 04:52:32.876 if ai == bj:
2025-07-02 04:52:32.876 if eqi is None:
2025-07-02 04:52:32.876 eqi, eqj = i, j
2025-07-02 04:52:32.876 continue
2025-07-02 04:52:32.876 cruncher.set_seq1(ai)
2025-07-02 04:52:32.876 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.876 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.876 # compares by a factor of 3.
2025-07-02 04:52:32.876 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.877 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.877 # of the computation is cached by cruncher
2025-07-02 04:52:32.877 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.877 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.877 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.877 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.877 if best_ratio < cutoff:
2025-07-02 04:52:32.877 # no non-identical "pretty close" pair
2025-07-02 04:52:32.877 if eqi is None:
2025-07-02 04:52:32.877 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.877 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.877 return
2025-07-02 04:52:32.877 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.877 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.877 else:
2025-07-02 04:52:32.877 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.877 eqi = None
2025-07-02 04:52:32.877
2025-07-02 04:52:32.877 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.877 # identical
2025-07-02 04:52:32.878
2025-07-02 04:52:32.878 # pump out diffs from before the synch point
2025-07-02 04:52:32.878 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.878
2025-07-02 04:52:32.878 # do intraline marking on the synch pair
2025-07-02 04:52:32.878 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.878 if eqi is None:
2025-07-02 04:52:32.878 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.878 atags = btags = ""
2025-07-02 04:52:32.878 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.878 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.878 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.878 if tag == 'replace':
2025-07-02 04:52:32.878 atags += '^' * la
2025-07-02 04:52:32.878 btags += '^' * lb
2025-07-02 04:52:32.878 elif tag == 'delete':
2025-07-02 04:52:32.878 atags += '-' * la
2025-07-02 04:52:32.878 elif tag == 'insert':
2025-07-02 04:52:32.878 btags += '+' * lb
2025-07-02 04:52:32.879 elif tag == 'equal':
2025-07-02 04:52:32.879 atags += ' ' * la
2025-07-02 04:52:32.879 btags += ' ' * lb
2025-07-02 04:52:32.879 else:
2025-07-02 04:52:32.879 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.879 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.879 else:
2025-07-02 04:52:32.879 # the synch pair is identical
2025-07-02 04:52:32.879 yield ' ' + aelt
2025-07-02 04:52:32.879
2025-07-02 04:52:32.879 # pump out diffs from after the synch point
2025-07-02 04:52:32.879 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.879
2025-07-02 04:52:32.879 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.879 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.879
2025-07-02 04:52:32.879 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.879 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.879 alo = 304, ahi = 1101
2025-07-02 04:52:32.879 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.880 blo = 304, bhi = 1101
2025-07-02 04:52:32.880
2025-07-02 04:52:32.880 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.880 g = []
2025-07-02 04:52:32.880 if alo < ahi:
2025-07-02 04:52:32.880 if blo < bhi:
2025-07-02 04:52:32.880 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.880 else:
2025-07-02 04:52:32.880 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.880 elif blo < bhi:
2025-07-02 04:52:32.880 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.880
2025-07-02 04:52:32.880 > yield from g
2025-07-02 04:52:32.880
2025-07-02 04:52:32.880 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.880 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.880
2025-07-02 04:52:32.880 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.880 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.881 alo = 304, ahi = 1101
2025-07-02 04:52:32.881 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.881 blo = 304, bhi = 1101
2025-07-02 04:52:32.881
2025-07-02 04:52:32.881 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.881 r"""
2025-07-02 04:52:32.881 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.881 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.881 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.881 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.881
2025-07-02 04:52:32.881 Example:
2025-07-02 04:52:32.881
2025-07-02 04:52:32.881 >>> d = Differ()
2025-07-02 04:52:32.881 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.881 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.881 >>> print(''.join(results), end="")
2025-07-02 04:52:32.881 - abcDefghiJkl
2025-07-02 04:52:32.882 + abcdefGhijkl
2025-07-02 04:52:32.882 """
2025-07-02 04:52:32.882
2025-07-02 04:52:32.882 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.882 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.882 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.882 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.882 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.882
2025-07-02 04:52:32.882 # search for the pair that matches best without being identical
2025-07-02 04:52:32.882 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.882 # on junk -- unless we have to)
2025-07-02 04:52:32.882 for j in range(blo, bhi):
2025-07-02 04:52:32.882 bj = b[j]
2025-07-02 04:52:32.882 cruncher.set_seq2(bj)
2025-07-02 04:52:32.882 for i in range(alo, ahi):
2025-07-02 04:52:32.882 ai = a[i]
2025-07-02 04:52:32.882 if ai == bj:
2025-07-02 04:52:32.882 if eqi is None:
2025-07-02 04:52:32.883 eqi, eqj = i, j
2025-07-02 04:52:32.883 continue
2025-07-02 04:52:32.883 cruncher.set_seq1(ai)
2025-07-02 04:52:32.883 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.883 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.883 # compares by a factor of 3.
2025-07-02 04:52:32.883 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.883 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.883 # of the computation is cached by cruncher
2025-07-02 04:52:32.883 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.883 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.883 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.883 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.883 if best_ratio < cutoff:
2025-07-02 04:52:32.883 # no non-identical "pretty close" pair
2025-07-02 04:52:32.883 if eqi is None:
2025-07-02 04:52:32.883 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.883 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.883 return
2025-07-02 04:52:32.883 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.883 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.884 else:
2025-07-02 04:52:32.884 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.884 eqi = None
2025-07-02 04:52:32.884
2025-07-02 04:52:32.884 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.884 # identical
2025-07-02 04:52:32.884
2025-07-02 04:52:32.884 # pump out diffs from before the synch point
2025-07-02 04:52:32.884 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.884
2025-07-02 04:52:32.884 # do intraline marking on the synch pair
2025-07-02 04:52:32.884 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.884 if eqi is None:
2025-07-02 04:52:32.884 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.884 atags = btags = ""
2025-07-02 04:52:32.884 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.884 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.884 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.884 if tag == 'replace':
2025-07-02 04:52:32.884 atags += '^' * la
2025-07-02 04:52:32.885 btags += '^' * lb
2025-07-02 04:52:32.885 elif tag == 'delete':
2025-07-02 04:52:32.885 atags += '-' * la
2025-07-02 04:52:32.885 elif tag == 'insert':
2025-07-02 04:52:32.885 btags += '+' * lb
2025-07-02 04:52:32.885 elif tag == 'equal':
2025-07-02 04:52:32.885 atags += ' ' * la
2025-07-02 04:52:32.885 btags += ' ' * lb
2025-07-02 04:52:32.885 else:
2025-07-02 04:52:32.885 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.885 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.885 else:
2025-07-02 04:52:32.885 # the synch pair is identical
2025-07-02 04:52:32.885 yield ' ' + aelt
2025-07-02 04:52:32.885
2025-07-02 04:52:32.885 # pump out diffs from after the synch point
2025-07-02 04:52:32.885 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.885
2025-07-02 04:52:32.885 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.885 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.885
2025-07-02 04:52:32.886 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.886 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.886 alo = 305, ahi = 1101
2025-07-02 04:52:32.886 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.886 blo = 305, bhi = 1101
2025-07-02 04:52:32.886
2025-07-02 04:52:32.886 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.886 g = []
2025-07-02 04:52:32.886 if alo < ahi:
2025-07-02 04:52:32.886 if blo < bhi:
2025-07-02 04:52:32.886 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.886 else:
2025-07-02 04:52:32.886 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.886 elif blo < bhi:
2025-07-02 04:52:32.886 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.886
2025-07-02 04:52:32.886 > yield from g
2025-07-02 04:52:32.886
2025-07-02 04:52:32.886 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.886 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.887
2025-07-02 04:52:32.887 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.887 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.887 alo = 305, ahi = 1101
2025-07-02 04:52:32.887 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.887 blo = 305, bhi = 1101
2025-07-02 04:52:32.887
2025-07-02 04:52:32.887 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.887 r"""
2025-07-02 04:52:32.887 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.887 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.887 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.887 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.887
2025-07-02 04:52:32.887 Example:
2025-07-02 04:52:32.887
2025-07-02 04:52:32.887 >>> d = Differ()
2025-07-02 04:52:32.887 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.887 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.887 >>> print(''.join(results), end="")
2025-07-02 04:52:32.887 - abcDefghiJkl
2025-07-02 04:52:32.888 + abcdefGhijkl
2025-07-02 04:52:32.888 """
2025-07-02 04:52:32.888
2025-07-02 04:52:32.888 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.888 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.888 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.888 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.888 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.888
2025-07-02 04:52:32.888 # search for the pair that matches best without being identical
2025-07-02 04:52:32.888 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.888 # on junk -- unless we have to)
2025-07-02 04:52:32.888 for j in range(blo, bhi):
2025-07-02 04:52:32.888 bj = b[j]
2025-07-02 04:52:32.888 cruncher.set_seq2(bj)
2025-07-02 04:52:32.888 for i in range(alo, ahi):
2025-07-02 04:52:32.888 ai = a[i]
2025-07-02 04:52:32.888 if ai == bj:
2025-07-02 04:52:32.889 if eqi is None:
2025-07-02 04:52:32.889 eqi, eqj = i, j
2025-07-02 04:52:32.889 continue
2025-07-02 04:52:32.889 cruncher.set_seq1(ai)
2025-07-02 04:52:32.889 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.889 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.889 # compares by a factor of 3.
2025-07-02 04:52:32.889 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.889 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.889 # of the computation is cached by cruncher
2025-07-02 04:52:32.889 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.889 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.889 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.889 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.889 if best_ratio < cutoff:
2025-07-02 04:52:32.889 # no non-identical "pretty close" pair
2025-07-02 04:52:32.889 if eqi is None:
2025-07-02 04:52:32.889 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.889 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.889 return
2025-07-02 04:52:32.890 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.890 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.890 else:
2025-07-02 04:52:32.890 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.890 eqi = None
2025-07-02 04:52:32.890
2025-07-02 04:52:32.890 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.890 # identical
2025-07-02 04:52:32.890
2025-07-02 04:52:32.890 # pump out diffs from before the synch point
2025-07-02 04:52:32.890 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.890
2025-07-02 04:52:32.890 # do intraline marking on the synch pair
2025-07-02 04:52:32.890 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.890 if eqi is None:
2025-07-02 04:52:32.890 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.890 atags = btags = ""
2025-07-02 04:52:32.890 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.890 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.890 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.890 if tag == 'replace':
2025-07-02 04:52:32.891 atags += '^' * la
2025-07-02 04:52:32.891 btags += '^' * lb
2025-07-02 04:52:32.891 elif tag == 'delete':
2025-07-02 04:52:32.891 atags += '-' * la
2025-07-02 04:52:32.891 elif tag == 'insert':
2025-07-02 04:52:32.891 btags += '+' * lb
2025-07-02 04:52:32.891 elif tag == 'equal':
2025-07-02 04:52:32.891 atags += ' ' * la
2025-07-02 04:52:32.891 btags += ' ' * lb
2025-07-02 04:52:32.891 else:
2025-07-02 04:52:32.891 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.891 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.891 else:
2025-07-02 04:52:32.891 # the synch pair is identical
2025-07-02 04:52:32.891 yield ' ' + aelt
2025-07-02 04:52:32.891
2025-07-02 04:52:32.891 # pump out diffs from after the synch point
2025-07-02 04:52:32.891 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.891
2025-07-02 04:52:32.891 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.891 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.892
2025-07-02 04:52:32.892 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.892 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.892 alo = 306, ahi = 1101
2025-07-02 04:52:32.892 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.892 blo = 306, bhi = 1101
2025-07-02 04:52:32.892
2025-07-02 04:52:32.892 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.892 g = []
2025-07-02 04:52:32.892 if alo < ahi:
2025-07-02 04:52:32.892 if blo < bhi:
2025-07-02 04:52:32.892 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.892 else:
2025-07-02 04:52:32.892 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.892 elif blo < bhi:
2025-07-02 04:52:32.892 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.892
2025-07-02 04:52:32.892 > yield from g
2025-07-02 04:52:32.892
2025-07-02 04:52:32.893 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.893 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.893
2025-07-02 04:52:32.893 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.893 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.893 alo = 306, ahi = 1101
2025-07-02 04:52:32.893 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.893 blo = 306, bhi = 1101
2025-07-02 04:52:32.893
2025-07-02 04:52:32.893 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.893 r"""
2025-07-02 04:52:32.893 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.893 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.893 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.893 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.893
2025-07-02 04:52:32.893 Example:
2025-07-02 04:52:32.893
2025-07-02 04:52:32.893 >>> d = Differ()
2025-07-02 04:52:32.893 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.893 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.894 >>> print(''.join(results), end="")
2025-07-02 04:52:32.894 - abcDefghiJkl
2025-07-02 04:52:32.894 + abcdefGhijkl
2025-07-02 04:52:32.894 """
2025-07-02 04:52:32.894
2025-07-02 04:52:32.894 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.894 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.894 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.894 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.894 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.894
2025-07-02 04:52:32.894 # search for the pair that matches best without being identical
2025-07-02 04:52:32.894 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.894 # on junk -- unless we have to)
2025-07-02 04:52:32.894 for j in range(blo, bhi):
2025-07-02 04:52:32.894 bj = b[j]
2025-07-02 04:52:32.894 cruncher.set_seq2(bj)
2025-07-02 04:52:32.894 for i in range(alo, ahi):
2025-07-02 04:52:32.895 ai = a[i]
2025-07-02 04:52:32.895 if ai == bj:
2025-07-02 04:52:32.895 if eqi is None:
2025-07-02 04:52:32.895 eqi, eqj = i, j
2025-07-02 04:52:32.895 continue
2025-07-02 04:52:32.895 cruncher.set_seq1(ai)
2025-07-02 04:52:32.895 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.895 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.895 # compares by a factor of 3.
2025-07-02 04:52:32.895 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.895 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.895 # of the computation is cached by cruncher
2025-07-02 04:52:32.895 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.895 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.895 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.895 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.895 if best_ratio < cutoff:
2025-07-02 04:52:32.895 # no non-identical "pretty close" pair
2025-07-02 04:52:32.895 if eqi is None:
2025-07-02 04:52:32.895 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.895 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.896 return
2025-07-02 04:52:32.896 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.896 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.896 else:
2025-07-02 04:52:32.896 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.896 eqi = None
2025-07-02 04:52:32.896
2025-07-02 04:52:32.896 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.896 # identical
2025-07-02 04:52:32.896
2025-07-02 04:52:32.896 # pump out diffs from before the synch point
2025-07-02 04:52:32.896 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.896
2025-07-02 04:52:32.896 # do intraline marking on the synch pair
2025-07-02 04:52:32.896 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.896 if eqi is None:
2025-07-02 04:52:32.896 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.896 atags = btags = ""
2025-07-02 04:52:32.896 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.896 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.896 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.896 if tag == 'replace':
2025-07-02 04:52:32.897 atags += '^' * la
2025-07-02 04:52:32.897 btags += '^' * lb
2025-07-02 04:52:32.897 elif tag == 'delete':
2025-07-02 04:52:32.897 atags += '-' * la
2025-07-02 04:52:32.897 elif tag == 'insert':
2025-07-02 04:52:32.897 btags += '+' * lb
2025-07-02 04:52:32.897 elif tag == 'equal':
2025-07-02 04:52:32.897 atags += ' ' * la
2025-07-02 04:52:32.897 btags += ' ' * lb
2025-07-02 04:52:32.897 else:
2025-07-02 04:52:32.897 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.897 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.897 else:
2025-07-02 04:52:32.897 # the synch pair is identical
2025-07-02 04:52:32.897 yield ' ' + aelt
2025-07-02 04:52:32.897
2025-07-02 04:52:32.897 # pump out diffs from after the synch point
2025-07-02 04:52:32.897 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.897
2025-07-02 04:52:32.898 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.898 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.898
2025-07-02 04:52:32.898 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.898 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.898 alo = 307, ahi = 1101
2025-07-02 04:52:32.898 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.898 blo = 307, bhi = 1101
2025-07-02 04:52:32.898
2025-07-02 04:52:32.898 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.898 g = []
2025-07-02 04:52:32.898 if alo < ahi:
2025-07-02 04:52:32.898 if blo < bhi:
2025-07-02 04:52:32.898 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.898 else:
2025-07-02 04:52:32.898 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.898 elif blo < bhi:
2025-07-02 04:52:32.898 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.898
2025-07-02 04:52:32.898 > yield from g
2025-07-02 04:52:32.899
2025-07-02 04:52:32.899 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.899 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.899
2025-07-02 04:52:32.899 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.899 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.899 alo = 307, ahi = 1101
2025-07-02 04:52:32.899 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.899 blo = 307, bhi = 1101
2025-07-02 04:52:32.899
2025-07-02 04:52:32.899 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.899 r"""
2025-07-02 04:52:32.899 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.899 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.899 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.899 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.899
2025-07-02 04:52:32.899 Example:
2025-07-02 04:52:32.899
2025-07-02 04:52:32.899 >>> d = Differ()
2025-07-02 04:52:32.899 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.900 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.900 >>> print(''.join(results), end="")
2025-07-02 04:52:32.900 - abcDefghiJkl
2025-07-02 04:52:32.900 + abcdefGhijkl
2025-07-02 04:52:32.900 """
2025-07-02 04:52:32.900
2025-07-02 04:52:32.900 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.900 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.900 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.900 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.900 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.900
2025-07-02 04:52:32.900 # search for the pair that matches best without being identical
2025-07-02 04:52:32.900 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.900 # on junk -- unless we have to)
2025-07-02 04:52:32.900 for j in range(blo, bhi):
2025-07-02 04:52:32.900 bj = b[j]
2025-07-02 04:52:32.900 cruncher.set_seq2(bj)
2025-07-02 04:52:32.900 for i in range(alo, ahi):
2025-07-02 04:52:32.901 ai = a[i]
2025-07-02 04:52:32.901 if ai == bj:
2025-07-02 04:52:32.901 if eqi is None:
2025-07-02 04:52:32.901 eqi, eqj = i, j
2025-07-02 04:52:32.901 continue
2025-07-02 04:52:32.901 cruncher.set_seq1(ai)
2025-07-02 04:52:32.901 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.901 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.901 # compares by a factor of 3.
2025-07-02 04:52:32.901 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.901 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.901 # of the computation is cached by cruncher
2025-07-02 04:52:32.901 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.901 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.901 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.901 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.901 if best_ratio < cutoff:
2025-07-02 04:52:32.901 # no non-identical "pretty close" pair
2025-07-02 04:52:32.901 if eqi is None:
2025-07-02 04:52:32.901 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.901 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.902 return
2025-07-02 04:52:32.902 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.902 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.902 else:
2025-07-02 04:52:32.902 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.902 eqi = None
2025-07-02 04:52:32.902
2025-07-02 04:52:32.902 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.902 # identical
2025-07-02 04:52:32.902
2025-07-02 04:52:32.902 # pump out diffs from before the synch point
2025-07-02 04:52:32.902 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.902
2025-07-02 04:52:32.902 # do intraline marking on the synch pair
2025-07-02 04:52:32.902 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.902 if eqi is None:
2025-07-02 04:52:32.902 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.902 atags = btags = ""
2025-07-02 04:52:32.902 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.902 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.902 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.902 if tag == 'replace':
2025-07-02 04:52:32.903 atags += '^' * la
2025-07-02 04:52:32.903 btags += '^' * lb
2025-07-02 04:52:32.903 elif tag == 'delete':
2025-07-02 04:52:32.903 atags += '-' * la
2025-07-02 04:52:32.903 elif tag == 'insert':
2025-07-02 04:52:32.903 btags += '+' * lb
2025-07-02 04:52:32.903 elif tag == 'equal':
2025-07-02 04:52:32.903 atags += ' ' * la
2025-07-02 04:52:32.903 btags += ' ' * lb
2025-07-02 04:52:32.903 else:
2025-07-02 04:52:32.903 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.903 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.903 else:
2025-07-02 04:52:32.903 # the synch pair is identical
2025-07-02 04:52:32.903 yield ' ' + aelt
2025-07-02 04:52:32.903
2025-07-02 04:52:32.903 # pump out diffs from after the synch point
2025-07-02 04:52:32.903 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.903
2025-07-02 04:52:32.903 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.903 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.904
2025-07-02 04:52:32.904 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.904 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.904 alo = 308, ahi = 1101
2025-07-02 04:52:32.904 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.904 blo = 308, bhi = 1101
2025-07-02 04:52:32.904
2025-07-02 04:52:32.904 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.904 g = []
2025-07-02 04:52:32.904 if alo < ahi:
2025-07-02 04:52:32.904 if blo < bhi:
2025-07-02 04:52:32.904 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.904 else:
2025-07-02 04:52:32.904 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.904 elif blo < bhi:
2025-07-02 04:52:32.904 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.904
2025-07-02 04:52:32.904 > yield from g
2025-07-02 04:52:32.904
2025-07-02 04:52:32.905 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.905 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.905
2025-07-02 04:52:32.905 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.905 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.905 alo = 308, ahi = 1101
2025-07-02 04:52:32.905 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.905 blo = 308, bhi = 1101
2025-07-02 04:52:32.905
2025-07-02 04:52:32.905 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.905 r"""
2025-07-02 04:52:32.905 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.905 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.905 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.905 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.905
2025-07-02 04:52:32.905 Example:
2025-07-02 04:52:32.905
2025-07-02 04:52:32.905 >>> d = Differ()
2025-07-02 04:52:32.906 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.906 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.906 >>> print(''.join(results), end="")
2025-07-02 04:52:32.906 - abcDefghiJkl
2025-07-02 04:52:32.906 + abcdefGhijkl
2025-07-02 04:52:32.906 """
2025-07-02 04:52:32.906
2025-07-02 04:52:32.906 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.906 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.906 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.906 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.906 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.906
2025-07-02 04:52:32.906 # search for the pair that matches best without being identical
2025-07-02 04:52:32.906 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.906 # on junk -- unless we have to)
2025-07-02 04:52:32.906 for j in range(blo, bhi):
2025-07-02 04:52:32.906 bj = b[j]
2025-07-02 04:52:32.906 cruncher.set_seq2(bj)
2025-07-02 04:52:32.907 for i in range(alo, ahi):
2025-07-02 04:52:32.907 ai = a[i]
2025-07-02 04:52:32.907 if ai == bj:
2025-07-02 04:52:32.907 if eqi is None:
2025-07-02 04:52:32.907 eqi, eqj = i, j
2025-07-02 04:52:32.907 continue
2025-07-02 04:52:32.907 cruncher.set_seq1(ai)
2025-07-02 04:52:32.907 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.907 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.907 # compares by a factor of 3.
2025-07-02 04:52:32.907 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.907 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.907 # of the computation is cached by cruncher
2025-07-02 04:52:32.907 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.907 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.907 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.907 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.907 if best_ratio < cutoff:
2025-07-02 04:52:32.907 # no non-identical "pretty close" pair
2025-07-02 04:52:32.907 if eqi is None:
2025-07-02 04:52:32.908 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.908 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.908 return
2025-07-02 04:52:32.908 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.908 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.908 else:
2025-07-02 04:52:32.908 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.908 eqi = None
2025-07-02 04:52:32.908
2025-07-02 04:52:32.908 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.908 # identical
2025-07-02 04:52:32.908
2025-07-02 04:52:32.908 # pump out diffs from before the synch point
2025-07-02 04:52:32.908 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.908
2025-07-02 04:52:32.908 # do intraline marking on the synch pair
2025-07-02 04:52:32.908 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.908 if eqi is None:
2025-07-02 04:52:32.908 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.909 atags = btags = ""
2025-07-02 04:52:32.909 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.909 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.909 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.909 if tag == 'replace':
2025-07-02 04:52:32.909 atags += '^' * la
2025-07-02 04:52:32.909 btags += '^' * lb
2025-07-02 04:52:32.909 elif tag == 'delete':
2025-07-02 04:52:32.909 atags += '-' * la
2025-07-02 04:52:32.909 elif tag == 'insert':
2025-07-02 04:52:32.909 btags += '+' * lb
2025-07-02 04:52:32.909 elif tag == 'equal':
2025-07-02 04:52:32.909 atags += ' ' * la
2025-07-02 04:52:32.909 btags += ' ' * lb
2025-07-02 04:52:32.909 else:
2025-07-02 04:52:32.909 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.909 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.909 else:
2025-07-02 04:52:32.909 # the synch pair is identical
2025-07-02 04:52:32.910 yield ' ' + aelt
2025-07-02 04:52:32.910
2025-07-02 04:52:32.910 # pump out diffs from after the synch point
2025-07-02 04:52:32.910 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.910
2025-07-02 04:52:32.910 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.910 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.910
2025-07-02 04:52:32.910 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.910 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.910 alo = 309, ahi = 1101
2025-07-02 04:52:32.910 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.910 blo = 309, bhi = 1101
2025-07-02 04:52:32.910
2025-07-02 04:52:32.910 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.910 g = []
2025-07-02 04:52:32.910 if alo < ahi:
2025-07-02 04:52:32.910 if blo < bhi:
2025-07-02 04:52:32.910 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.911 else:
2025-07-02 04:52:32.911 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.911 elif blo < bhi:
2025-07-02 04:52:32.911 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.911
2025-07-02 04:52:32.911 > yield from g
2025-07-02 04:52:32.911
2025-07-02 04:52:32.911 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.911 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.911
2025-07-02 04:52:32.911 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.911 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.911 alo = 309, ahi = 1101
2025-07-02 04:52:32.911 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.911 blo = 309, bhi = 1101
2025-07-02 04:52:32.911
2025-07-02 04:52:32.911 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.911 r"""
2025-07-02 04:52:32.911 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.911 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.912 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.912 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.912
2025-07-02 04:52:32.912 Example:
2025-07-02 04:52:32.912
2025-07-02 04:52:32.912 >>> d = Differ()
2025-07-02 04:52:32.912 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.912 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.912 >>> print(''.join(results), end="")
2025-07-02 04:52:32.912 - abcDefghiJkl
2025-07-02 04:52:32.912 + abcdefGhijkl
2025-07-02 04:52:32.912 """
2025-07-02 04:52:32.912
2025-07-02 04:52:32.912 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.912 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.912 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.912 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.912 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.912
2025-07-02 04:52:32.913 # search for the pair that matches best without being identical
2025-07-02 04:52:32.913 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.913 # on junk -- unless we have to)
2025-07-02 04:52:32.913 for j in range(blo, bhi):
2025-07-02 04:52:32.913 bj = b[j]
2025-07-02 04:52:32.913 cruncher.set_seq2(bj)
2025-07-02 04:52:32.913 for i in range(alo, ahi):
2025-07-02 04:52:32.913 ai = a[i]
2025-07-02 04:52:32.913 if ai == bj:
2025-07-02 04:52:32.913 if eqi is None:
2025-07-02 04:52:32.913 eqi, eqj = i, j
2025-07-02 04:52:32.913 continue
2025-07-02 04:52:32.913 cruncher.set_seq1(ai)
2025-07-02 04:52:32.913 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.913 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.913 # compares by a factor of 3.
2025-07-02 04:52:32.913 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.913 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.913 # of the computation is cached by cruncher
2025-07-02 04:52:32.913 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.913 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.914 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.914 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.914 if best_ratio < cutoff:
2025-07-02 04:52:32.914 # no non-identical "pretty close" pair
2025-07-02 04:52:32.914 if eqi is None:
2025-07-02 04:52:32.914 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.914 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.914 return
2025-07-02 04:52:32.914 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.914 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.914 else:
2025-07-02 04:52:32.914 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.914 eqi = None
2025-07-02 04:52:32.914
2025-07-02 04:52:32.914 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.914 # identical
2025-07-02 04:52:32.914
2025-07-02 04:52:32.914 # pump out diffs from before the synch point
2025-07-02 04:52:32.914 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.915
2025-07-02 04:52:32.915 # do intraline marking on the synch pair
2025-07-02 04:52:32.915 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.915 if eqi is None:
2025-07-02 04:52:32.915 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.915 atags = btags = ""
2025-07-02 04:52:32.915 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.915 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.915 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.915 if tag == 'replace':
2025-07-02 04:52:32.915 atags += '^' * la
2025-07-02 04:52:32.915 btags += '^' * lb
2025-07-02 04:52:32.915 elif tag == 'delete':
2025-07-02 04:52:32.915 atags += '-' * la
2025-07-02 04:52:32.915 elif tag == 'insert':
2025-07-02 04:52:32.915 btags += '+' * lb
2025-07-02 04:52:32.915 elif tag == 'equal':
2025-07-02 04:52:32.915 atags += ' ' * la
2025-07-02 04:52:32.915 btags += ' ' * lb
2025-07-02 04:52:32.915 else:
2025-07-02 04:52:32.915 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.916 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.916 else:
2025-07-02 04:52:32.916 # the synch pair is identical
2025-07-02 04:52:32.916 yield ' ' + aelt
2025-07-02 04:52:32.916
2025-07-02 04:52:32.916 # pump out diffs from after the synch point
2025-07-02 04:52:32.916 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.916
2025-07-02 04:52:32.916 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.916 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.916
2025-07-02 04:52:32.916 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.916 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.916 alo = 312, ahi = 1101
2025-07-02 04:52:32.916 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.916 blo = 312, bhi = 1101
2025-07-02 04:52:32.916
2025-07-02 04:52:32.916 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.916 g = []
2025-07-02 04:52:32.916 if alo < ahi:
2025-07-02 04:52:32.917 if blo < bhi:
2025-07-02 04:52:32.917 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.917 else:
2025-07-02 04:52:32.917 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.917 elif blo < bhi:
2025-07-02 04:52:32.917 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.917
2025-07-02 04:52:32.917 > yield from g
2025-07-02 04:52:32.917
2025-07-02 04:52:32.917 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.917 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.917
2025-07-02 04:52:32.917 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.917 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.917 alo = 312, ahi = 1101
2025-07-02 04:52:32.917 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.917 blo = 312, bhi = 1101
2025-07-02 04:52:32.917
2025-07-02 04:52:32.917 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.917 r"""
2025-07-02 04:52:32.918 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.918 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.918 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.918 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.918
2025-07-02 04:52:32.918 Example:
2025-07-02 04:52:32.918
2025-07-02 04:52:32.918 >>> d = Differ()
2025-07-02 04:52:32.918 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.918 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.918 >>> print(''.join(results), end="")
2025-07-02 04:52:32.918 - abcDefghiJkl
2025-07-02 04:52:32.918 + abcdefGhijkl
2025-07-02 04:52:32.918 """
2025-07-02 04:52:32.918
2025-07-02 04:52:32.918 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.918 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.918 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.918 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.919 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.919
2025-07-02 04:52:32.919 # search for the pair that matches best without being identical
2025-07-02 04:52:32.919 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.919 # on junk -- unless we have to)
2025-07-02 04:52:32.919 for j in range(blo, bhi):
2025-07-02 04:52:32.919 bj = b[j]
2025-07-02 04:52:32.919 cruncher.set_seq2(bj)
2025-07-02 04:52:32.919 for i in range(alo, ahi):
2025-07-02 04:52:32.919 ai = a[i]
2025-07-02 04:52:32.919 if ai == bj:
2025-07-02 04:52:32.919 if eqi is None:
2025-07-02 04:52:32.919 eqi, eqj = i, j
2025-07-02 04:52:32.919 continue
2025-07-02 04:52:32.919 cruncher.set_seq1(ai)
2025-07-02 04:52:32.919 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.919 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.919 # compares by a factor of 3.
2025-07-02 04:52:32.919 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.919 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.919 # of the computation is cached by cruncher
2025-07-02 04:52:32.920 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.920 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.920 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.920 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.920 if best_ratio < cutoff:
2025-07-02 04:52:32.920 # no non-identical "pretty close" pair
2025-07-02 04:52:32.920 if eqi is None:
2025-07-02 04:52:32.920 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.920 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.920 return
2025-07-02 04:52:32.920 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.920 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.920 else:
2025-07-02 04:52:32.920 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.920 eqi = None
2025-07-02 04:52:32.920
2025-07-02 04:52:32.920 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.920 # identical
2025-07-02 04:52:32.920
2025-07-02 04:52:32.920 # pump out diffs from before the synch point
2025-07-02 04:52:32.921 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.921
2025-07-02 04:52:32.921 # do intraline marking on the synch pair
2025-07-02 04:52:32.921 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.921 if eqi is None:
2025-07-02 04:52:32.921 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.921 atags = btags = ""
2025-07-02 04:52:32.921 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.921 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.921 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.921 if tag == 'replace':
2025-07-02 04:52:32.921 atags += '^' * la
2025-07-02 04:52:32.921 btags += '^' * lb
2025-07-02 04:52:32.921 elif tag == 'delete':
2025-07-02 04:52:32.921 atags += '-' * la
2025-07-02 04:52:32.921 elif tag == 'insert':
2025-07-02 04:52:32.921 btags += '+' * lb
2025-07-02 04:52:32.921 elif tag == 'equal':
2025-07-02 04:52:32.921 atags += ' ' * la
2025-07-02 04:52:32.921 btags += ' ' * lb
2025-07-02 04:52:32.921 else:
2025-07-02 04:52:32.922 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.922 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.922 else:
2025-07-02 04:52:32.922 # the synch pair is identical
2025-07-02 04:52:32.922 yield ' ' + aelt
2025-07-02 04:52:32.922
2025-07-02 04:52:32.922 # pump out diffs from after the synch point
2025-07-02 04:52:32.922 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.922
2025-07-02 04:52:32.922 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.922 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.922
2025-07-02 04:52:32.922 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.922 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.922 alo = 313, ahi = 1101
2025-07-02 04:52:32.922 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.922 blo = 313, bhi = 1101
2025-07-02 04:52:32.922
2025-07-02 04:52:32.922 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.922 g = []
2025-07-02 04:52:32.923 if alo < ahi:
2025-07-02 04:52:32.923 if blo < bhi:
2025-07-02 04:52:32.923 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.923 else:
2025-07-02 04:52:32.923 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.923 elif blo < bhi:
2025-07-02 04:52:32.923 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.923
2025-07-02 04:52:32.923 > yield from g
2025-07-02 04:52:32.923
2025-07-02 04:52:32.923 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.923 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.923
2025-07-02 04:52:32.923 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.923 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.923 alo = 313, ahi = 1101
2025-07-02 04:52:32.923 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.923 blo = 313, bhi = 1101
2025-07-02 04:52:32.923
2025-07-02 04:52:32.923 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.924 r"""
2025-07-02 04:52:32.924 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.924 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.924 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.924 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.924
2025-07-02 04:52:32.924 Example:
2025-07-02 04:52:32.924
2025-07-02 04:52:32.924 >>> d = Differ()
2025-07-02 04:52:32.924 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.924 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.924 >>> print(''.join(results), end="")
2025-07-02 04:52:32.924 - abcDefghiJkl
2025-07-02 04:52:32.924 + abcdefGhijkl
2025-07-02 04:52:32.924 """
2025-07-02 04:52:32.924
2025-07-02 04:52:32.924 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.925 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.925 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.925 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.925 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.925
2025-07-02 04:52:32.925 # search for the pair that matches best without being identical
2025-07-02 04:52:32.925 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.925 # on junk -- unless we have to)
2025-07-02 04:52:32.925 for j in range(blo, bhi):
2025-07-02 04:52:32.925 bj = b[j]
2025-07-02 04:52:32.925 cruncher.set_seq2(bj)
2025-07-02 04:52:32.925 for i in range(alo, ahi):
2025-07-02 04:52:32.925 ai = a[i]
2025-07-02 04:52:32.925 if ai == bj:
2025-07-02 04:52:32.925 if eqi is None:
2025-07-02 04:52:32.925 eqi, eqj = i, j
2025-07-02 04:52:32.925 continue
2025-07-02 04:52:32.925 cruncher.set_seq1(ai)
2025-07-02 04:52:32.925 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.925 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.925 # compares by a factor of 3.
2025-07-02 04:52:32.926 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.926 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.926 # of the computation is cached by cruncher
2025-07-02 04:52:32.926 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.926 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.926 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.926 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.926 if best_ratio < cutoff:
2025-07-02 04:52:32.926 # no non-identical "pretty close" pair
2025-07-02 04:52:32.926 if eqi is None:
2025-07-02 04:52:32.926 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.926 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.926 return
2025-07-02 04:52:32.926 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.926 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.926 else:
2025-07-02 04:52:32.926 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.926 eqi = None
2025-07-02 04:52:32.926
2025-07-02 04:52:32.926 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.926 # identical
2025-07-02 04:52:32.927
2025-07-02 04:52:32.927 # pump out diffs from before the synch point
2025-07-02 04:52:32.927 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.927
2025-07-02 04:52:32.927 # do intraline marking on the synch pair
2025-07-02 04:52:32.927 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.927 if eqi is None:
2025-07-02 04:52:32.927 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.927 atags = btags = ""
2025-07-02 04:52:32.927 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.927 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.927 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.927 if tag == 'replace':
2025-07-02 04:52:32.927 atags += '^' * la
2025-07-02 04:52:32.927 btags += '^' * lb
2025-07-02 04:52:32.927 elif tag == 'delete':
2025-07-02 04:52:32.927 atags += '-' * la
2025-07-02 04:52:32.927 elif tag == 'insert':
2025-07-02 04:52:32.927 btags += '+' * lb
2025-07-02 04:52:32.927 elif tag == 'equal':
2025-07-02 04:52:32.928 atags += ' ' * la
2025-07-02 04:52:32.928 btags += ' ' * lb
2025-07-02 04:52:32.928 else:
2025-07-02 04:52:32.928 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.928 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.928 else:
2025-07-02 04:52:32.928 # the synch pair is identical
2025-07-02 04:52:32.928 yield ' ' + aelt
2025-07-02 04:52:32.928
2025-07-02 04:52:32.928 # pump out diffs from after the synch point
2025-07-02 04:52:32.928 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.928
2025-07-02 04:52:32.928 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.928 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.928
2025-07-02 04:52:32.928 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.928 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.928 alo = 314, ahi = 1101
2025-07-02 04:52:32.928 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.928 blo = 314, bhi = 1101
2025-07-02 04:52:32.928
2025-07-02 04:52:32.929 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.929 g = []
2025-07-02 04:52:32.929 if alo < ahi:
2025-07-02 04:52:32.929 if blo < bhi:
2025-07-02 04:52:32.929 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.929 else:
2025-07-02 04:52:32.929 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.929 elif blo < bhi:
2025-07-02 04:52:32.929 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.929
2025-07-02 04:52:32.929 > yield from g
2025-07-02 04:52:32.929
2025-07-02 04:52:32.929 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.929 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.929
2025-07-02 04:52:32.929 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.929 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.929 alo = 314, ahi = 1101
2025-07-02 04:52:32.929 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.929 blo = 314, bhi = 1101
2025-07-02 04:52:32.930
2025-07-02 04:52:32.930 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.930 r"""
2025-07-02 04:52:32.930 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.930 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.930 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.930 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.930
2025-07-02 04:52:32.930 Example:
2025-07-02 04:52:32.930
2025-07-02 04:52:32.930 >>> d = Differ()
2025-07-02 04:52:32.930 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.930 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.930 >>> print(''.join(results), end="")
2025-07-02 04:52:32.930 - abcDefghiJkl
2025-07-02 04:52:32.930 + abcdefGhijkl
2025-07-02 04:52:32.930 """
2025-07-02 04:52:32.930
2025-07-02 04:52:32.930 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.931 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.931 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.931 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.931 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.931
2025-07-02 04:52:32.931 # search for the pair that matches best without being identical
2025-07-02 04:52:32.931 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.931 # on junk -- unless we have to)
2025-07-02 04:52:32.931 for j in range(blo, bhi):
2025-07-02 04:52:32.931 bj = b[j]
2025-07-02 04:52:32.931 cruncher.set_seq2(bj)
2025-07-02 04:52:32.931 for i in range(alo, ahi):
2025-07-02 04:52:32.931 ai = a[i]
2025-07-02 04:52:32.931 if ai == bj:
2025-07-02 04:52:32.931 if eqi is None:
2025-07-02 04:52:32.931 eqi, eqj = i, j
2025-07-02 04:52:32.931 continue
2025-07-02 04:52:32.931 cruncher.set_seq1(ai)
2025-07-02 04:52:32.931 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.931 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.932 # compares by a factor of 3.
2025-07-02 04:52:32.932 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.932 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.932 # of the computation is cached by cruncher
2025-07-02 04:52:32.932 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.932 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.932 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.932 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.932 if best_ratio < cutoff:
2025-07-02 04:52:32.932 # no non-identical "pretty close" pair
2025-07-02 04:52:32.932 if eqi is None:
2025-07-02 04:52:32.932 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.932 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.932 return
2025-07-02 04:52:32.932 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.932 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.932 else:
2025-07-02 04:52:32.932 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.932 eqi = None
2025-07-02 04:52:32.932
2025-07-02 04:52:32.933 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.933 # identical
2025-07-02 04:52:32.933
2025-07-02 04:52:32.933 # pump out diffs from before the synch point
2025-07-02 04:52:32.933 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.933
2025-07-02 04:52:32.933 # do intraline marking on the synch pair
2025-07-02 04:52:32.933 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.933 if eqi is None:
2025-07-02 04:52:32.933 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.933 atags = btags = ""
2025-07-02 04:52:32.933 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.933 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.933 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.933 if tag == 'replace':
2025-07-02 04:52:32.933 atags += '^' * la
2025-07-02 04:52:32.933 btags += '^' * lb
2025-07-02 04:52:32.933 elif tag == 'delete':
2025-07-02 04:52:32.933 atags += '-' * la
2025-07-02 04:52:32.933 elif tag == 'insert':
2025-07-02 04:52:32.933 btags += '+' * lb
2025-07-02 04:52:32.934 elif tag == 'equal':
2025-07-02 04:52:32.934 atags += ' ' * la
2025-07-02 04:52:32.934 btags += ' ' * lb
2025-07-02 04:52:32.934 else:
2025-07-02 04:52:32.934 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.934 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.934 else:
2025-07-02 04:52:32.934 # the synch pair is identical
2025-07-02 04:52:32.934 yield ' ' + aelt
2025-07-02 04:52:32.934
2025-07-02 04:52:32.934 # pump out diffs from after the synch point
2025-07-02 04:52:32.934 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.934
2025-07-02 04:52:32.934 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.934 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.934
2025-07-02 04:52:32.934 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.934 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.934 alo = 315, ahi = 1101
2025-07-02 04:52:32.934 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.935 blo = 315, bhi = 1101
2025-07-02 04:52:32.935
2025-07-02 04:52:32.935 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.935 g = []
2025-07-02 04:52:32.935 if alo < ahi:
2025-07-02 04:52:32.935 if blo < bhi:
2025-07-02 04:52:32.935 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.935 else:
2025-07-02 04:52:32.935 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.935 elif blo < bhi:
2025-07-02 04:52:32.935 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.935
2025-07-02 04:52:32.935 > yield from g
2025-07-02 04:52:32.935
2025-07-02 04:52:32.935 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.935 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.935
2025-07-02 04:52:32.935 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.935 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.935 alo = 315, ahi = 1101
2025-07-02 04:52:32.935 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.936 blo = 315, bhi = 1101
2025-07-02 04:52:32.936
2025-07-02 04:52:32.936 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.936 r"""
2025-07-02 04:52:32.936 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.936 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.936 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.936 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.936
2025-07-02 04:52:32.936 Example:
2025-07-02 04:52:32.936
2025-07-02 04:52:32.936 >>> d = Differ()
2025-07-02 04:52:32.936 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.936 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.936 >>> print(''.join(results), end="")
2025-07-02 04:52:32.936 - abcDefghiJkl
2025-07-02 04:52:32.936 + abcdefGhijkl
2025-07-02 04:52:32.936 """
2025-07-02 04:52:32.937
2025-07-02 04:52:32.937 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.937 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.937 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.937 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.937 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.937
2025-07-02 04:52:32.937 # search for the pair that matches best without being identical
2025-07-02 04:52:32.937 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.937 # on junk -- unless we have to)
2025-07-02 04:52:32.937 for j in range(blo, bhi):
2025-07-02 04:52:32.937 bj = b[j]
2025-07-02 04:52:32.937 cruncher.set_seq2(bj)
2025-07-02 04:52:32.937 for i in range(alo, ahi):
2025-07-02 04:52:32.937 ai = a[i]
2025-07-02 04:52:32.937 if ai == bj:
2025-07-02 04:52:32.937 if eqi is None:
2025-07-02 04:52:32.937 eqi, eqj = i, j
2025-07-02 04:52:32.937 continue
2025-07-02 04:52:32.937 cruncher.set_seq1(ai)
2025-07-02 04:52:32.937 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.938 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.938 # compares by a factor of 3.
2025-07-02 04:52:32.938 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.938 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.938 # of the computation is cached by cruncher
2025-07-02 04:52:32.938 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.938 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.938 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.938 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.938 if best_ratio < cutoff:
2025-07-02 04:52:32.938 # no non-identical "pretty close" pair
2025-07-02 04:52:32.938 if eqi is None:
2025-07-02 04:52:32.938 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.938 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.938 return
2025-07-02 04:52:32.938 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.938 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.938 else:
2025-07-02 04:52:32.938 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.938 eqi = None
2025-07-02 04:52:32.939
2025-07-02 04:52:32.939 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.939 # identical
2025-07-02 04:52:32.939
2025-07-02 04:52:32.939 # pump out diffs from before the synch point
2025-07-02 04:52:32.939 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.939
2025-07-02 04:52:32.939 # do intraline marking on the synch pair
2025-07-02 04:52:32.939 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.939 if eqi is None:
2025-07-02 04:52:32.939 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.939 atags = btags = ""
2025-07-02 04:52:32.939 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.939 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.939 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.939 if tag == 'replace':
2025-07-02 04:52:32.939 atags += '^' * la
2025-07-02 04:52:32.939 btags += '^' * lb
2025-07-02 04:52:32.939 elif tag == 'delete':
2025-07-02 04:52:32.939 atags += '-' * la
2025-07-02 04:52:32.940 elif tag == 'insert':
2025-07-02 04:52:32.940 btags += '+' * lb
2025-07-02 04:52:32.940 elif tag == 'equal':
2025-07-02 04:52:32.940 atags += ' ' * la
2025-07-02 04:52:32.940 btags += ' ' * lb
2025-07-02 04:52:32.940 else:
2025-07-02 04:52:32.940 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.940 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.940 else:
2025-07-02 04:52:32.940 # the synch pair is identical
2025-07-02 04:52:32.940 yield ' ' + aelt
2025-07-02 04:52:32.940
2025-07-02 04:52:32.940 # pump out diffs from after the synch point
2025-07-02 04:52:32.940 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.940
2025-07-02 04:52:32.940 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.940 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.940
2025-07-02 04:52:32.940 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.941 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.941 alo = 316, ahi = 1101
2025-07-02 04:52:32.941 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.941 blo = 316, bhi = 1101
2025-07-02 04:52:32.941
2025-07-02 04:52:32.941 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.941 g = []
2025-07-02 04:52:32.941 if alo < ahi:
2025-07-02 04:52:32.941 if blo < bhi:
2025-07-02 04:52:32.941 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.941 else:
2025-07-02 04:52:32.941 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.941 elif blo < bhi:
2025-07-02 04:52:32.941 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.941
2025-07-02 04:52:32.941 > yield from g
2025-07-02 04:52:32.941
2025-07-02 04:52:32.941 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.941 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.941
2025-07-02 04:52:32.942 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.942 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.942 alo = 316, ahi = 1101
2025-07-02 04:52:32.942 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.942 blo = 316, bhi = 1101
2025-07-02 04:52:32.942
2025-07-02 04:52:32.942 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.942 r"""
2025-07-02 04:52:32.942 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.942 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.942 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.942 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.942
2025-07-02 04:52:32.942 Example:
2025-07-02 04:52:32.942
2025-07-02 04:52:32.942 >>> d = Differ()
2025-07-02 04:52:32.942 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.942 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.942 >>> print(''.join(results), end="")
2025-07-02 04:52:32.942 - abcDefghiJkl
2025-07-02 04:52:32.943 + abcdefGhijkl
2025-07-02 04:52:32.943 """
2025-07-02 04:52:32.943
2025-07-02 04:52:32.943 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.943 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.943 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.943 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.943 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.943
2025-07-02 04:52:32.943 # search for the pair that matches best without being identical
2025-07-02 04:52:32.943 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.943 # on junk -- unless we have to)
2025-07-02 04:52:32.943 for j in range(blo, bhi):
2025-07-02 04:52:32.943 bj = b[j]
2025-07-02 04:52:32.943 cruncher.set_seq2(bj)
2025-07-02 04:52:32.943 for i in range(alo, ahi):
2025-07-02 04:52:32.943 ai = a[i]
2025-07-02 04:52:32.943 if ai == bj:
2025-07-02 04:52:32.943 if eqi is None:
2025-07-02 04:52:32.944 eqi, eqj = i, j
2025-07-02 04:52:32.944 continue
2025-07-02 04:52:32.944 cruncher.set_seq1(ai)
2025-07-02 04:52:32.944 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.944 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.944 # compares by a factor of 3.
2025-07-02 04:52:32.944 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.944 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.944 # of the computation is cached by cruncher
2025-07-02 04:52:32.944 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.944 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.944 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.944 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.944 if best_ratio < cutoff:
2025-07-02 04:52:32.944 # no non-identical "pretty close" pair
2025-07-02 04:52:32.944 if eqi is None:
2025-07-02 04:52:32.944 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.944 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.944 return
2025-07-02 04:52:32.944 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.944 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.945 else:
2025-07-02 04:52:32.945 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.945 eqi = None
2025-07-02 04:52:32.945
2025-07-02 04:52:32.945 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.945 # identical
2025-07-02 04:52:32.945
2025-07-02 04:52:32.945 # pump out diffs from before the synch point
2025-07-02 04:52:32.945 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.945
2025-07-02 04:52:32.945 # do intraline marking on the synch pair
2025-07-02 04:52:32.945 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.945 if eqi is None:
2025-07-02 04:52:32.945 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.945 atags = btags = ""
2025-07-02 04:52:32.945 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.945 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.945 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.945 if tag == 'replace':
2025-07-02 04:52:32.945 atags += '^' * la
2025-07-02 04:52:32.945 btags += '^' * lb
2025-07-02 04:52:32.945 elif tag == 'delete':
2025-07-02 04:52:32.946 atags += '-' * la
2025-07-02 04:52:32.946 elif tag == 'insert':
2025-07-02 04:52:32.946 btags += '+' * lb
2025-07-02 04:52:32.946 elif tag == 'equal':
2025-07-02 04:52:32.946 atags += ' ' * la
2025-07-02 04:52:32.946 btags += ' ' * lb
2025-07-02 04:52:32.946 else:
2025-07-02 04:52:32.946 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.946 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.946 else:
2025-07-02 04:52:32.946 # the synch pair is identical
2025-07-02 04:52:32.946 yield ' ' + aelt
2025-07-02 04:52:32.946
2025-07-02 04:52:32.946 # pump out diffs from after the synch point
2025-07-02 04:52:32.946 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.946
2025-07-02 04:52:32.946 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.946 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.946
2025-07-02 04:52:32.946 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.946 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.947 alo = 317, ahi = 1101
2025-07-02 04:52:32.947 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.947 blo = 317, bhi = 1101
2025-07-02 04:52:32.947
2025-07-02 04:52:32.947 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.947 g = []
2025-07-02 04:52:32.947 if alo < ahi:
2025-07-02 04:52:32.947 if blo < bhi:
2025-07-02 04:52:32.947 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.947 else:
2025-07-02 04:52:32.947 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.947 elif blo < bhi:
2025-07-02 04:52:32.947 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.947
2025-07-02 04:52:32.947 > yield from g
2025-07-02 04:52:32.947
2025-07-02 04:52:32.947 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.947 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.947
2025-07-02 04:52:32.947 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.947 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.947 alo = 317, ahi = 1101
2025-07-02 04:52:32.948 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.948 blo = 317, bhi = 1101
2025-07-02 04:52:32.948
2025-07-02 04:52:32.948 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.948 r"""
2025-07-02 04:52:32.948 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.948 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.948 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.948 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.948
2025-07-02 04:52:32.948 Example:
2025-07-02 04:52:32.948
2025-07-02 04:52:32.948 >>> d = Differ()
2025-07-02 04:52:32.948 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.948 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.948 >>> print(''.join(results), end="")
2025-07-02 04:52:32.948 - abcDefghiJkl
2025-07-02 04:52:32.949 + abcdefGhijkl
2025-07-02 04:52:32.949 """
2025-07-02 04:52:32.949
2025-07-02 04:52:32.949 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.949 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.949 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.949 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.949 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.949
2025-07-02 04:52:32.949 # search for the pair that matches best without being identical
2025-07-02 04:52:32.949 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.949 # on junk -- unless we have to)
2025-07-02 04:52:32.949 for j in range(blo, bhi):
2025-07-02 04:52:32.949 bj = b[j]
2025-07-02 04:52:32.949 cruncher.set_seq2(bj)
2025-07-02 04:52:32.949 for i in range(alo, ahi):
2025-07-02 04:52:32.949 ai = a[i]
2025-07-02 04:52:32.949 if ai == bj:
2025-07-02 04:52:32.949 if eqi is None:
2025-07-02 04:52:32.949 eqi, eqj = i, j
2025-07-02 04:52:32.950 continue
2025-07-02 04:52:32.950 cruncher.set_seq1(ai)
2025-07-02 04:52:32.950 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.950 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.950 # compares by a factor of 3.
2025-07-02 04:52:32.950 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.950 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.950 # of the computation is cached by cruncher
2025-07-02 04:52:32.950 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.950 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.950 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.950 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.950 if best_ratio < cutoff:
2025-07-02 04:52:32.950 # no non-identical "pretty close" pair
2025-07-02 04:52:32.950 if eqi is None:
2025-07-02 04:52:32.950 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.950 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.950 return
2025-07-02 04:52:32.950 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.950 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.950 else:
2025-07-02 04:52:32.951 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.951 eqi = None
2025-07-02 04:52:32.951
2025-07-02 04:52:32.951 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.951 # identical
2025-07-02 04:52:32.951
2025-07-02 04:52:32.951 # pump out diffs from before the synch point
2025-07-02 04:52:32.951 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.951
2025-07-02 04:52:32.951 # do intraline marking on the synch pair
2025-07-02 04:52:32.951 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.951 if eqi is None:
2025-07-02 04:52:32.951 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.951 atags = btags = ""
2025-07-02 04:52:32.951 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.951 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.951 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.951 if tag == 'replace':
2025-07-02 04:52:32.951 atags += '^' * la
2025-07-02 04:52:32.951 btags += '^' * lb
2025-07-02 04:52:32.951 elif tag == 'delete':
2025-07-02 04:52:32.951 atags += '-' * la
2025-07-02 04:52:32.952 elif tag == 'insert':
2025-07-02 04:52:32.952 btags += '+' * lb
2025-07-02 04:52:32.952 elif tag == 'equal':
2025-07-02 04:52:32.952 atags += ' ' * la
2025-07-02 04:52:32.952 btags += ' ' * lb
2025-07-02 04:52:32.952 else:
2025-07-02 04:52:32.952 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.952 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.952 else:
2025-07-02 04:52:32.952 # the synch pair is identical
2025-07-02 04:52:32.952 yield ' ' + aelt
2025-07-02 04:52:32.952
2025-07-02 04:52:32.952 # pump out diffs from after the synch point
2025-07-02 04:52:32.952 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.952
2025-07-02 04:52:32.952 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.952 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.952
2025-07-02 04:52:32.952 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.952 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.952 alo = 318, ahi = 1101
2025-07-02 04:52:32.953 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.953 blo = 318, bhi = 1101
2025-07-02 04:52:32.953
2025-07-02 04:52:32.953 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.953 g = []
2025-07-02 04:52:32.953 if alo < ahi:
2025-07-02 04:52:32.953 if blo < bhi:
2025-07-02 04:52:32.953 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.953 else:
2025-07-02 04:52:32.953 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.953 elif blo < bhi:
2025-07-02 04:52:32.953 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.953
2025-07-02 04:52:32.953 > yield from g
2025-07-02 04:52:32.953
2025-07-02 04:52:32.953 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.953 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.953
2025-07-02 04:52:32.953 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.953 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.953 alo = 318, ahi = 1101
2025-07-02 04:52:32.954 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.954 blo = 318, bhi = 1101
2025-07-02 04:52:32.954
2025-07-02 04:52:32.954 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.954 r"""
2025-07-02 04:52:32.954 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.954 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.954 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.954 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.954
2025-07-02 04:52:32.954 Example:
2025-07-02 04:52:32.954
2025-07-02 04:52:32.954 >>> d = Differ()
2025-07-02 04:52:32.954 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.954 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.954 >>> print(''.join(results), end="")
2025-07-02 04:52:32.954 - abcDefghiJkl
2025-07-02 04:52:32.954 + abcdefGhijkl
2025-07-02 04:52:32.954 """
2025-07-02 04:52:32.954
2025-07-02 04:52:32.955 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.955 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.955 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.955 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.955 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.955
2025-07-02 04:52:32.955 # search for the pair that matches best without being identical
2025-07-02 04:52:32.955 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.955 # on junk -- unless we have to)
2025-07-02 04:52:32.955 for j in range(blo, bhi):
2025-07-02 04:52:32.955 bj = b[j]
2025-07-02 04:52:32.955 cruncher.set_seq2(bj)
2025-07-02 04:52:32.955 for i in range(alo, ahi):
2025-07-02 04:52:32.955 ai = a[i]
2025-07-02 04:52:32.955 if ai == bj:
2025-07-02 04:52:32.955 if eqi is None:
2025-07-02 04:52:32.955 eqi, eqj = i, j
2025-07-02 04:52:32.955 continue
2025-07-02 04:52:32.955 cruncher.set_seq1(ai)
2025-07-02 04:52:32.955 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.955 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.956 # compares by a factor of 3.
2025-07-02 04:52:32.956 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.956 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.956 # of the computation is cached by cruncher
2025-07-02 04:52:32.956 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.956 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.956 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.956 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.956 if best_ratio < cutoff:
2025-07-02 04:52:32.956 # no non-identical "pretty close" pair
2025-07-02 04:52:32.956 if eqi is None:
2025-07-02 04:52:32.956 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.956 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.956 return
2025-07-02 04:52:32.956 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.956 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.956 else:
2025-07-02 04:52:32.956 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.957 eqi = None
2025-07-02 04:52:32.957
2025-07-02 04:52:32.957 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.957 # identical
2025-07-02 04:52:32.957
2025-07-02 04:52:32.957 # pump out diffs from before the synch point
2025-07-02 04:52:32.957 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.957
2025-07-02 04:52:32.957 # do intraline marking on the synch pair
2025-07-02 04:52:32.957 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.957 if eqi is None:
2025-07-02 04:52:32.957 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.957 atags = btags = ""
2025-07-02 04:52:32.957 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.957 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.957 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.957 if tag == 'replace':
2025-07-02 04:52:32.957 atags += '^' * la
2025-07-02 04:52:32.957 btags += '^' * lb
2025-07-02 04:52:32.957 elif tag == 'delete':
2025-07-02 04:52:32.957 atags += '-' * la
2025-07-02 04:52:32.958 elif tag == 'insert':
2025-07-02 04:52:32.958 btags += '+' * lb
2025-07-02 04:52:32.958 elif tag == 'equal':
2025-07-02 04:52:32.958 atags += ' ' * la
2025-07-02 04:52:32.958 btags += ' ' * lb
2025-07-02 04:52:32.958 else:
2025-07-02 04:52:32.958 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.958 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.958 else:
2025-07-02 04:52:32.958 # the synch pair is identical
2025-07-02 04:52:32.958 yield ' ' + aelt
2025-07-02 04:52:32.958
2025-07-02 04:52:32.958 # pump out diffs from after the synch point
2025-07-02 04:52:32.958 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.958
2025-07-02 04:52:32.958 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.958 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.958
2025-07-02 04:52:32.958 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.958 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.959 alo = 319, ahi = 1101
2025-07-02 04:52:32.959 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.959 blo = 319, bhi = 1101
2025-07-02 04:52:32.959
2025-07-02 04:52:32.959 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.959 g = []
2025-07-02 04:52:32.959 if alo < ahi:
2025-07-02 04:52:32.959 if blo < bhi:
2025-07-02 04:52:32.959 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.959 else:
2025-07-02 04:52:32.959 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.959 elif blo < bhi:
2025-07-02 04:52:32.959 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.959
2025-07-02 04:52:32.959 > yield from g
2025-07-02 04:52:32.959
2025-07-02 04:52:32.959 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.959 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.959
2025-07-02 04:52:32.959 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.959 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.960 alo = 319, ahi = 1101
2025-07-02 04:52:32.960 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.960 blo = 319, bhi = 1101
2025-07-02 04:52:32.960
2025-07-02 04:52:32.960 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.960 r"""
2025-07-02 04:52:32.960 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.960 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.960 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.960 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.960
2025-07-02 04:52:32.960 Example:
2025-07-02 04:52:32.960
2025-07-02 04:52:32.960 >>> d = Differ()
2025-07-02 04:52:32.960 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.960 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.960 >>> print(''.join(results), end="")
2025-07-02 04:52:32.960 - abcDefghiJkl
2025-07-02 04:52:32.960 + abcdefGhijkl
2025-07-02 04:52:32.961 """
2025-07-02 04:52:32.961
2025-07-02 04:52:32.961 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.961 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.961 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.961 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.961 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.961
2025-07-02 04:52:32.961 # search for the pair that matches best without being identical
2025-07-02 04:52:32.961 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.961 # on junk -- unless we have to)
2025-07-02 04:52:32.961 for j in range(blo, bhi):
2025-07-02 04:52:32.961 bj = b[j]
2025-07-02 04:52:32.961 cruncher.set_seq2(bj)
2025-07-02 04:52:32.961 for i in range(alo, ahi):
2025-07-02 04:52:32.961 ai = a[i]
2025-07-02 04:52:32.961 if ai == bj:
2025-07-02 04:52:32.961 if eqi is None:
2025-07-02 04:52:32.961 eqi, eqj = i, j
2025-07-02 04:52:32.961 continue
2025-07-02 04:52:32.962 cruncher.set_seq1(ai)
2025-07-02 04:52:32.962 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.962 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.962 # compares by a factor of 3.
2025-07-02 04:52:32.962 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.962 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.962 # of the computation is cached by cruncher
2025-07-02 04:52:32.962 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.962 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.962 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.962 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.962 if best_ratio < cutoff:
2025-07-02 04:52:32.962 # no non-identical "pretty close" pair
2025-07-02 04:52:32.962 if eqi is None:
2025-07-02 04:52:32.962 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.962 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.962 return
2025-07-02 04:52:32.962 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.962 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.962 else:
2025-07-02 04:52:32.962 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.963 eqi = None
2025-07-02 04:52:32.963
2025-07-02 04:52:32.963 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.963 # identical
2025-07-02 04:52:32.963
2025-07-02 04:52:32.963 # pump out diffs from before the synch point
2025-07-02 04:52:32.963 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.963
2025-07-02 04:52:32.963 # do intraline marking on the synch pair
2025-07-02 04:52:32.963 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.963 if eqi is None:
2025-07-02 04:52:32.963 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.963 atags = btags = ""
2025-07-02 04:52:32.963 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.963 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.963 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.963 if tag == 'replace':
2025-07-02 04:52:32.963 atags += '^' * la
2025-07-02 04:52:32.963 btags += '^' * lb
2025-07-02 04:52:32.963 elif tag == 'delete':
2025-07-02 04:52:32.963 atags += '-' * la
2025-07-02 04:52:32.964 elif tag == 'insert':
2025-07-02 04:52:32.964 btags += '+' * lb
2025-07-02 04:52:32.964 elif tag == 'equal':
2025-07-02 04:52:32.964 atags += ' ' * la
2025-07-02 04:52:32.964 btags += ' ' * lb
2025-07-02 04:52:32.964 else:
2025-07-02 04:52:32.964 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.964 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.964 else:
2025-07-02 04:52:32.964 # the synch pair is identical
2025-07-02 04:52:32.964 yield ' ' + aelt
2025-07-02 04:52:32.964
2025-07-02 04:52:32.964 # pump out diffs from after the synch point
2025-07-02 04:52:32.964 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.964
2025-07-02 04:52:32.964 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.964 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.964
2025-07-02 04:52:32.964 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.964 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.965 alo = 320, ahi = 1101
2025-07-02 04:52:32.965 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.965 blo = 320, bhi = 1101
2025-07-02 04:52:32.965
2025-07-02 04:52:32.965 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.965 g = []
2025-07-02 04:52:32.965 if alo < ahi:
2025-07-02 04:52:32.965 if blo < bhi:
2025-07-02 04:52:32.965 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.965 else:
2025-07-02 04:52:32.965 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.965 elif blo < bhi:
2025-07-02 04:52:32.965 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.965
2025-07-02 04:52:32.965 > yield from g
2025-07-02 04:52:32.965
2025-07-02 04:52:32.965 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.965 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.965
2025-07-02 04:52:32.965 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.966 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.966 alo = 320, ahi = 1101
2025-07-02 04:52:32.966 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.966 blo = 320, bhi = 1101
2025-07-02 04:52:32.966
2025-07-02 04:52:32.966 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.966 r"""
2025-07-02 04:52:32.966 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.966 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.966 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.966 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.966
2025-07-02 04:52:32.966 Example:
2025-07-02 04:52:32.966
2025-07-02 04:52:32.966 >>> d = Differ()
2025-07-02 04:52:32.966 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.966 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.966 >>> print(''.join(results), end="")
2025-07-02 04:52:32.966 - abcDefghiJkl
2025-07-02 04:52:32.967 + abcdefGhijkl
2025-07-02 04:52:32.967 """
2025-07-02 04:52:32.967
2025-07-02 04:52:32.967 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.967 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.967 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.967 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.967 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.967
2025-07-02 04:52:32.967 # search for the pair that matches best without being identical
2025-07-02 04:52:32.967 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.967 # on junk -- unless we have to)
2025-07-02 04:52:32.967 for j in range(blo, bhi):
2025-07-02 04:52:32.967 bj = b[j]
2025-07-02 04:52:32.967 cruncher.set_seq2(bj)
2025-07-02 04:52:32.967 for i in range(alo, ahi):
2025-07-02 04:52:32.967 ai = a[i]
2025-07-02 04:52:32.967 if ai == bj:
2025-07-02 04:52:32.967 if eqi is None:
2025-07-02 04:52:32.967 eqi, eqj = i, j
2025-07-02 04:52:32.968 continue
2025-07-02 04:52:32.968 cruncher.set_seq1(ai)
2025-07-02 04:52:32.968 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.968 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.968 # compares by a factor of 3.
2025-07-02 04:52:32.968 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.968 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.968 # of the computation is cached by cruncher
2025-07-02 04:52:32.968 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.968 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.968 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.968 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.968 if best_ratio < cutoff:
2025-07-02 04:52:32.968 # no non-identical "pretty close" pair
2025-07-02 04:52:32.968 if eqi is None:
2025-07-02 04:52:32.968 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.968 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.968 return
2025-07-02 04:52:32.968 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.968 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.969 else:
2025-07-02 04:52:32.969 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.969 eqi = None
2025-07-02 04:52:32.969
2025-07-02 04:52:32.969 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.969 # identical
2025-07-02 04:52:32.969
2025-07-02 04:52:32.969 # pump out diffs from before the synch point
2025-07-02 04:52:32.969 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.969
2025-07-02 04:52:32.969 # do intraline marking on the synch pair
2025-07-02 04:52:32.969 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.969 if eqi is None:
2025-07-02 04:52:32.969 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.969 atags = btags = ""
2025-07-02 04:52:32.969 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.969 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.969 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.969 if tag == 'replace':
2025-07-02 04:52:32.969 atags += '^' * la
2025-07-02 04:52:32.969 btags += '^' * lb
2025-07-02 04:52:32.969 elif tag == 'delete':
2025-07-02 04:52:32.970 atags += '-' * la
2025-07-02 04:52:32.970 elif tag == 'insert':
2025-07-02 04:52:32.970 btags += '+' * lb
2025-07-02 04:52:32.970 elif tag == 'equal':
2025-07-02 04:52:32.970 atags += ' ' * la
2025-07-02 04:52:32.970 btags += ' ' * lb
2025-07-02 04:52:32.970 else:
2025-07-02 04:52:32.970 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.970 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.970 else:
2025-07-02 04:52:32.970 # the synch pair is identical
2025-07-02 04:52:32.970 yield ' ' + aelt
2025-07-02 04:52:32.970
2025-07-02 04:52:32.970 # pump out diffs from after the synch point
2025-07-02 04:52:32.970 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.970
2025-07-02 04:52:32.970 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.970 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.970
2025-07-02 04:52:32.970 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.970 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.971 alo = 321, ahi = 1101
2025-07-02 04:52:32.971 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.971 blo = 321, bhi = 1101
2025-07-02 04:52:32.971
2025-07-02 04:52:32.971 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.971 g = []
2025-07-02 04:52:32.971 if alo < ahi:
2025-07-02 04:52:32.971 if blo < bhi:
2025-07-02 04:52:32.971 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.971 else:
2025-07-02 04:52:32.971 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.971 elif blo < bhi:
2025-07-02 04:52:32.971 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.971
2025-07-02 04:52:32.971 > yield from g
2025-07-02 04:52:32.971
2025-07-02 04:52:32.971 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.971 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.971
2025-07-02 04:52:32.972 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.972 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.972 alo = 321, ahi = 1101
2025-07-02 04:52:32.972 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.972 blo = 321, bhi = 1101
2025-07-02 04:52:32.972
2025-07-02 04:52:32.972 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.972 r"""
2025-07-02 04:52:32.972 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.972 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.972 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.972 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.972
2025-07-02 04:52:32.972 Example:
2025-07-02 04:52:32.972
2025-07-02 04:52:32.972 >>> d = Differ()
2025-07-02 04:52:32.972 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.972 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.972 >>> print(''.join(results), end="")
2025-07-02 04:52:32.972 - abcDefghiJkl
2025-07-02 04:52:32.973 + abcdefGhijkl
2025-07-02 04:52:32.973 """
2025-07-02 04:52:32.973
2025-07-02 04:52:32.973 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.973 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.973 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.973 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.973 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.973
2025-07-02 04:52:32.973 # search for the pair that matches best without being identical
2025-07-02 04:52:32.973 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.973 # on junk -- unless we have to)
2025-07-02 04:52:32.973 for j in range(blo, bhi):
2025-07-02 04:52:32.973 bj = b[j]
2025-07-02 04:52:32.973 cruncher.set_seq2(bj)
2025-07-02 04:52:32.973 for i in range(alo, ahi):
2025-07-02 04:52:32.973 ai = a[i]
2025-07-02 04:52:32.973 if ai == bj:
2025-07-02 04:52:32.974 if eqi is None:
2025-07-02 04:52:32.974 eqi, eqj = i, j
2025-07-02 04:52:32.974 continue
2025-07-02 04:52:32.974 cruncher.set_seq1(ai)
2025-07-02 04:52:32.974 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.974 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.974 # compares by a factor of 3.
2025-07-02 04:52:32.974 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.974 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.974 # of the computation is cached by cruncher
2025-07-02 04:52:32.974 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.974 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.974 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.974 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.974 if best_ratio < cutoff:
2025-07-02 04:52:32.974 # no non-identical "pretty close" pair
2025-07-02 04:52:32.974 if eqi is None:
2025-07-02 04:52:32.974 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.974 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.974 return
2025-07-02 04:52:32.975 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.975 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.975 else:
2025-07-02 04:52:32.975 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.975 eqi = None
2025-07-02 04:52:32.975
2025-07-02 04:52:32.975 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.975 # identical
2025-07-02 04:52:32.975
2025-07-02 04:52:32.975 # pump out diffs from before the synch point
2025-07-02 04:52:32.975 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.975
2025-07-02 04:52:32.975 # do intraline marking on the synch pair
2025-07-02 04:52:32.975 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.975 if eqi is None:
2025-07-02 04:52:32.975 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.975 atags = btags = ""
2025-07-02 04:52:32.975 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.975 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.975 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.975 if tag == 'replace':
2025-07-02 04:52:32.976 atags += '^' * la
2025-07-02 04:52:32.976 btags += '^' * lb
2025-07-02 04:52:32.976 elif tag == 'delete':
2025-07-02 04:52:32.976 atags += '-' * la
2025-07-02 04:52:32.976 elif tag == 'insert':
2025-07-02 04:52:32.976 btags += '+' * lb
2025-07-02 04:52:32.976 elif tag == 'equal':
2025-07-02 04:52:32.976 atags += ' ' * la
2025-07-02 04:52:32.976 btags += ' ' * lb
2025-07-02 04:52:32.976 else:
2025-07-02 04:52:32.976 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.976 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.976 else:
2025-07-02 04:52:32.976 # the synch pair is identical
2025-07-02 04:52:32.976 yield ' ' + aelt
2025-07-02 04:52:32.976
2025-07-02 04:52:32.976 # pump out diffs from after the synch point
2025-07-02 04:52:32.976 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.976
2025-07-02 04:52:32.976 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.976 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.977
2025-07-02 04:52:32.977 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.977 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.977 alo = 322, ahi = 1101
2025-07-02 04:52:32.977 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.977 blo = 322, bhi = 1101
2025-07-02 04:52:32.977
2025-07-02 04:52:32.977 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.977 g = []
2025-07-02 04:52:32.977 if alo < ahi:
2025-07-02 04:52:32.977 if blo < bhi:
2025-07-02 04:52:32.977 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.977 else:
2025-07-02 04:52:32.977 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.977 elif blo < bhi:
2025-07-02 04:52:32.977 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.977
2025-07-02 04:52:32.977 > yield from g
2025-07-02 04:52:32.977
2025-07-02 04:52:32.977 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.977 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.978
2025-07-02 04:52:32.978 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.978 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.978 alo = 322, ahi = 1101
2025-07-02 04:52:32.978 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.978 blo = 322, bhi = 1101
2025-07-02 04:52:32.978
2025-07-02 04:52:32.978 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.978 r"""
2025-07-02 04:52:32.978 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.978 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.978 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.978 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.978
2025-07-02 04:52:32.978 Example:
2025-07-02 04:52:32.978
2025-07-02 04:52:32.978 >>> d = Differ()
2025-07-02 04:52:32.978 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.978 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.978 >>> print(''.join(results), end="")
2025-07-02 04:52:32.978 - abcDefghiJkl
2025-07-02 04:52:32.979 + abcdefGhijkl
2025-07-02 04:52:32.979 """
2025-07-02 04:52:32.979
2025-07-02 04:52:32.979 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.979 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.979 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.979 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.979 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.979
2025-07-02 04:52:32.979 # search for the pair that matches best without being identical
2025-07-02 04:52:32.979 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.979 # on junk -- unless we have to)
2025-07-02 04:52:32.979 for j in range(blo, bhi):
2025-07-02 04:52:32.979 bj = b[j]
2025-07-02 04:52:32.979 cruncher.set_seq2(bj)
2025-07-02 04:52:32.979 for i in range(alo, ahi):
2025-07-02 04:52:32.979 ai = a[i]
2025-07-02 04:52:32.979 if ai == bj:
2025-07-02 04:52:32.979 if eqi is None:
2025-07-02 04:52:32.979 eqi, eqj = i, j
2025-07-02 04:52:32.980 continue
2025-07-02 04:52:32.980 cruncher.set_seq1(ai)
2025-07-02 04:52:32.980 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.980 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.980 # compares by a factor of 3.
2025-07-02 04:52:32.980 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.980 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.980 # of the computation is cached by cruncher
2025-07-02 04:52:32.980 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.980 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.980 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.980 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.980 if best_ratio < cutoff:
2025-07-02 04:52:32.980 # no non-identical "pretty close" pair
2025-07-02 04:52:32.980 if eqi is None:
2025-07-02 04:52:32.980 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.980 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.980 return
2025-07-02 04:52:32.980 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.980 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.980 else:
2025-07-02 04:52:32.980 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.981 eqi = None
2025-07-02 04:52:32.981
2025-07-02 04:52:32.981 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.981 # identical
2025-07-02 04:52:32.981
2025-07-02 04:52:32.981 # pump out diffs from before the synch point
2025-07-02 04:52:32.981 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.981
2025-07-02 04:52:32.981 # do intraline marking on the synch pair
2025-07-02 04:52:32.981 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.981 if eqi is None:
2025-07-02 04:52:32.981 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.981 atags = btags = ""
2025-07-02 04:52:32.981 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.981 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.981 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.981 if tag == 'replace':
2025-07-02 04:52:32.981 atags += '^' * la
2025-07-02 04:52:32.981 btags += '^' * lb
2025-07-02 04:52:32.982 elif tag == 'delete':
2025-07-02 04:52:32.982 atags += '-' * la
2025-07-02 04:52:32.982 elif tag == 'insert':
2025-07-02 04:52:32.982 btags += '+' * lb
2025-07-02 04:52:32.982 elif tag == 'equal':
2025-07-02 04:52:32.982 atags += ' ' * la
2025-07-02 04:52:32.982 btags += ' ' * lb
2025-07-02 04:52:32.982 else:
2025-07-02 04:52:32.982 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.982 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.982 else:
2025-07-02 04:52:32.982 # the synch pair is identical
2025-07-02 04:52:32.982 yield ' ' + aelt
2025-07-02 04:52:32.982
2025-07-02 04:52:32.982 # pump out diffs from after the synch point
2025-07-02 04:52:32.982 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.982
2025-07-02 04:52:32.982 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.982 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.982
2025-07-02 04:52:32.982 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.983 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.983 alo = 323, ahi = 1101
2025-07-02 04:52:32.983 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.983 blo = 323, bhi = 1101
2025-07-02 04:52:32.983
2025-07-02 04:52:32.983 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.983 g = []
2025-07-02 04:52:32.983 if alo < ahi:
2025-07-02 04:52:32.983 if blo < bhi:
2025-07-02 04:52:32.983 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.983 else:
2025-07-02 04:52:32.983 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.983 elif blo < bhi:
2025-07-02 04:52:32.983 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.983
2025-07-02 04:52:32.983 > yield from g
2025-07-02 04:52:32.983
2025-07-02 04:52:32.983 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.983 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.983
2025-07-02 04:52:32.984 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.984 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.984 alo = 323, ahi = 1101
2025-07-02 04:52:32.984 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.984 blo = 323, bhi = 1101
2025-07-02 04:52:32.984
2025-07-02 04:52:32.984 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.984 r"""
2025-07-02 04:52:32.984 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.984 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.984 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.984 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.984
2025-07-02 04:52:32.984 Example:
2025-07-02 04:52:32.984
2025-07-02 04:52:32.984 >>> d = Differ()
2025-07-02 04:52:32.984 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.984 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.984 >>> print(''.join(results), end="")
2025-07-02 04:52:32.984 - abcDefghiJkl
2025-07-02 04:52:32.985 + abcdefGhijkl
2025-07-02 04:52:32.985 """
2025-07-02 04:52:32.985
2025-07-02 04:52:32.985 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.985 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.985 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.985 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.985 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.985
2025-07-02 04:52:32.985 # search for the pair that matches best without being identical
2025-07-02 04:52:32.985 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.985 # on junk -- unless we have to)
2025-07-02 04:52:32.985 for j in range(blo, bhi):
2025-07-02 04:52:32.985 bj = b[j]
2025-07-02 04:52:32.985 cruncher.set_seq2(bj)
2025-07-02 04:52:32.985 for i in range(alo, ahi):
2025-07-02 04:52:32.985 ai = a[i]
2025-07-02 04:52:32.985 if ai == bj:
2025-07-02 04:52:32.985 if eqi is None:
2025-07-02 04:52:32.985 eqi, eqj = i, j
2025-07-02 04:52:32.986 continue
2025-07-02 04:52:32.986 cruncher.set_seq1(ai)
2025-07-02 04:52:32.986 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.986 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.986 # compares by a factor of 3.
2025-07-02 04:52:32.986 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.986 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.986 # of the computation is cached by cruncher
2025-07-02 04:52:32.986 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.986 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.986 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.986 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.986 if best_ratio < cutoff:
2025-07-02 04:52:32.986 # no non-identical "pretty close" pair
2025-07-02 04:52:32.986 if eqi is None:
2025-07-02 04:52:32.986 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.986 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.986 return
2025-07-02 04:52:32.986 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.987 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.987 else:
2025-07-02 04:52:32.987 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.987 eqi = None
2025-07-02 04:52:32.987
2025-07-02 04:52:32.987 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.987 # identical
2025-07-02 04:52:32.987
2025-07-02 04:52:32.987 # pump out diffs from before the synch point
2025-07-02 04:52:32.987 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.987
2025-07-02 04:52:32.987 # do intraline marking on the synch pair
2025-07-02 04:52:32.987 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.987 if eqi is None:
2025-07-02 04:52:32.987 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.987 atags = btags = ""
2025-07-02 04:52:32.987 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.987 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.987 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.987 if tag == 'replace':
2025-07-02 04:52:32.987 atags += '^' * la
2025-07-02 04:52:32.988 btags += '^' * lb
2025-07-02 04:52:32.988 elif tag == 'delete':
2025-07-02 04:52:32.988 atags += '-' * la
2025-07-02 04:52:32.988 elif tag == 'insert':
2025-07-02 04:52:32.988 btags += '+' * lb
2025-07-02 04:52:32.988 elif tag == 'equal':
2025-07-02 04:52:32.988 atags += ' ' * la
2025-07-02 04:52:32.988 btags += ' ' * lb
2025-07-02 04:52:32.988 else:
2025-07-02 04:52:32.988 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.988 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.988 else:
2025-07-02 04:52:32.988 # the synch pair is identical
2025-07-02 04:52:32.988 yield ' ' + aelt
2025-07-02 04:52:32.988
2025-07-02 04:52:32.988 # pump out diffs from after the synch point
2025-07-02 04:52:32.988 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.988
2025-07-02 04:52:32.988 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.988 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.988
2025-07-02 04:52:32.988 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.989 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.989 alo = 324, ahi = 1101
2025-07-02 04:52:32.989 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.989 blo = 324, bhi = 1101
2025-07-02 04:52:32.989
2025-07-02 04:52:32.989 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.989 g = []
2025-07-02 04:52:32.989 if alo < ahi:
2025-07-02 04:52:32.989 if blo < bhi:
2025-07-02 04:52:32.989 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.989 else:
2025-07-02 04:52:32.989 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.989 elif blo < bhi:
2025-07-02 04:52:32.989 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.989
2025-07-02 04:52:32.989 > yield from g
2025-07-02 04:52:32.989
2025-07-02 04:52:32.989 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.989 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.989
2025-07-02 04:52:32.989 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.990 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.990 alo = 324, ahi = 1101
2025-07-02 04:52:32.990 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.990 blo = 324, bhi = 1101
2025-07-02 04:52:32.990
2025-07-02 04:52:32.990 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.990 r"""
2025-07-02 04:52:32.990 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.990 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.990 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.990 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.990
2025-07-02 04:52:32.990 Example:
2025-07-02 04:52:32.990
2025-07-02 04:52:32.990 >>> d = Differ()
2025-07-02 04:52:32.990 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.990 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.990 >>> print(''.join(results), end="")
2025-07-02 04:52:32.991 - abcDefghiJkl
2025-07-02 04:52:32.991 + abcdefGhijkl
2025-07-02 04:52:32.991 """
2025-07-02 04:52:32.991
2025-07-02 04:52:32.991 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.991 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.991 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.991 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.991 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.991
2025-07-02 04:52:32.991 # search for the pair that matches best without being identical
2025-07-02 04:52:32.991 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.991 # on junk -- unless we have to)
2025-07-02 04:52:32.991 for j in range(blo, bhi):
2025-07-02 04:52:32.991 bj = b[j]
2025-07-02 04:52:32.991 cruncher.set_seq2(bj)
2025-07-02 04:52:32.991 for i in range(alo, ahi):
2025-07-02 04:52:32.991 ai = a[i]
2025-07-02 04:52:32.992 if ai == bj:
2025-07-02 04:52:32.992 if eqi is None:
2025-07-02 04:52:32.992 eqi, eqj = i, j
2025-07-02 04:52:32.992 continue
2025-07-02 04:52:32.992 cruncher.set_seq1(ai)
2025-07-02 04:52:32.992 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.992 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.992 # compares by a factor of 3.
2025-07-02 04:52:32.992 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.992 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.992 # of the computation is cached by cruncher
2025-07-02 04:52:32.992 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.992 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.992 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.992 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.992 if best_ratio < cutoff:
2025-07-02 04:52:32.992 # no non-identical "pretty close" pair
2025-07-02 04:52:32.992 if eqi is None:
2025-07-02 04:52:32.992 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.992 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.992 return
2025-07-02 04:52:32.993 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.993 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.993 else:
2025-07-02 04:52:32.993 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.993 eqi = None
2025-07-02 04:52:32.993
2025-07-02 04:52:32.993 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.993 # identical
2025-07-02 04:52:32.993
2025-07-02 04:52:32.993 # pump out diffs from before the synch point
2025-07-02 04:52:32.993 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.993
2025-07-02 04:52:32.993 # do intraline marking on the synch pair
2025-07-02 04:52:32.993 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.993 if eqi is None:
2025-07-02 04:52:32.993 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.993 atags = btags = ""
2025-07-02 04:52:32.993 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.993 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.993 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.993 if tag == 'replace':
2025-07-02 04:52:32.994 atags += '^' * la
2025-07-02 04:52:32.994 btags += '^' * lb
2025-07-02 04:52:32.994 elif tag == 'delete':
2025-07-02 04:52:32.994 atags += '-' * la
2025-07-02 04:52:32.994 elif tag == 'insert':
2025-07-02 04:52:32.994 btags += '+' * lb
2025-07-02 04:52:32.994 elif tag == 'equal':
2025-07-02 04:52:32.994 atags += ' ' * la
2025-07-02 04:52:32.994 btags += ' ' * lb
2025-07-02 04:52:32.994 else:
2025-07-02 04:52:32.994 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:32.994 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:32.994 else:
2025-07-02 04:52:32.994 # the synch pair is identical
2025-07-02 04:52:32.994 yield ' ' + aelt
2025-07-02 04:52:32.994
2025-07-02 04:52:32.994 # pump out diffs from after the synch point
2025-07-02 04:52:32.994 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:32.994
2025-07-02 04:52:32.994 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:32.994 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.994
2025-07-02 04:52:32.995 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.995 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.995 alo = 325, ahi = 1101
2025-07-02 04:52:32.995 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.995 blo = 325, bhi = 1101
2025-07-02 04:52:32.995
2025-07-02 04:52:32.995 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.995 g = []
2025-07-02 04:52:32.995 if alo < ahi:
2025-07-02 04:52:32.995 if blo < bhi:
2025-07-02 04:52:32.995 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.995 else:
2025-07-02 04:52:32.995 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:32.995 elif blo < bhi:
2025-07-02 04:52:32.995 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:32.995
2025-07-02 04:52:32.995 > yield from g
2025-07-02 04:52:32.995
2025-07-02 04:52:32.995 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:32.995 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:32.995
2025-07-02 04:52:32.996 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:32.996 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:32.996 alo = 325, ahi = 1101
2025-07-02 04:52:32.996 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:32.996 blo = 325, bhi = 1101
2025-07-02 04:52:32.996
2025-07-02 04:52:32.996 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:32.996 r"""
2025-07-02 04:52:32.996 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:32.996 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:32.996 synch point, and intraline difference marking is done on the
2025-07-02 04:52:32.996 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:32.996
2025-07-02 04:52:32.996 Example:
2025-07-02 04:52:32.996
2025-07-02 04:52:32.996 >>> d = Differ()
2025-07-02 04:52:32.996 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:32.996 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:32.996 >>> print(''.join(results), end="")
2025-07-02 04:52:32.996 - abcDefghiJkl
2025-07-02 04:52:32.997 + abcdefGhijkl
2025-07-02 04:52:32.997 """
2025-07-02 04:52:32.997
2025-07-02 04:52:32.997 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:32.997 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:32.997 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:32.997 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:32.997 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:32.997
2025-07-02 04:52:32.997 # search for the pair that matches best without being identical
2025-07-02 04:52:32.997 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:32.997 # on junk -- unless we have to)
2025-07-02 04:52:32.997 for j in range(blo, bhi):
2025-07-02 04:52:32.997 bj = b[j]
2025-07-02 04:52:32.997 cruncher.set_seq2(bj)
2025-07-02 04:52:32.997 for i in range(alo, ahi):
2025-07-02 04:52:32.997 ai = a[i]
2025-07-02 04:52:32.997 if ai == bj:
2025-07-02 04:52:32.997 if eqi is None:
2025-07-02 04:52:32.997 eqi, eqj = i, j
2025-07-02 04:52:32.998 continue
2025-07-02 04:52:32.998 cruncher.set_seq1(ai)
2025-07-02 04:52:32.998 # computing similarity is expensive, so use the quick
2025-07-02 04:52:32.998 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:32.998 # compares by a factor of 3.
2025-07-02 04:52:32.998 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:32.998 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:32.998 # of the computation is cached by cruncher
2025-07-02 04:52:32.998 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:32.998 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:32.998 cruncher.ratio() > best_ratio:
2025-07-02 04:52:32.998 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:32.998 if best_ratio < cutoff:
2025-07-02 04:52:32.998 # no non-identical "pretty close" pair
2025-07-02 04:52:32.998 if eqi is None:
2025-07-02 04:52:32.998 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:32.998 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:32.998 return
2025-07-02 04:52:32.998 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:32.999 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:32.999 else:
2025-07-02 04:52:32.999 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:32.999 eqi = None
2025-07-02 04:52:32.999
2025-07-02 04:52:32.999 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:32.999 # identical
2025-07-02 04:52:32.999
2025-07-02 04:52:32.999 # pump out diffs from before the synch point
2025-07-02 04:52:32.999 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:32.999
2025-07-02 04:52:32.999 # do intraline marking on the synch pair
2025-07-02 04:52:32.999 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:32.999 if eqi is None:
2025-07-02 04:52:32.999 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:32.999 atags = btags = ""
2025-07-02 04:52:32.999 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:32.999 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:32.999 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:32.999 if tag == 'replace':
2025-07-02 04:52:32.999 atags += '^' * la
2025-07-02 04:52:33.000 btags += '^' * lb
2025-07-02 04:52:33.000 elif tag == 'delete':
2025-07-02 04:52:33.000 atags += '-' * la
2025-07-02 04:52:33.000 elif tag == 'insert':
2025-07-02 04:52:33.000 btags += '+' * lb
2025-07-02 04:52:33.000 elif tag == 'equal':
2025-07-02 04:52:33.000 atags += ' ' * la
2025-07-02 04:52:33.000 btags += ' ' * lb
2025-07-02 04:52:33.000 else:
2025-07-02 04:52:33.000 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.000 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.000 else:
2025-07-02 04:52:33.000 # the synch pair is identical
2025-07-02 04:52:33.000 yield ' ' + aelt
2025-07-02 04:52:33.000
2025-07-02 04:52:33.000 # pump out diffs from after the synch point
2025-07-02 04:52:33.000 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.000
2025-07-02 04:52:33.000 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.000 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.000
2025-07-02 04:52:33.001 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.001 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.001 alo = 326, ahi = 1101
2025-07-02 04:52:33.001 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.001 blo = 326, bhi = 1101
2025-07-02 04:52:33.001
2025-07-02 04:52:33.001 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.001 g = []
2025-07-02 04:52:33.001 if alo < ahi:
2025-07-02 04:52:33.001 if blo < bhi:
2025-07-02 04:52:33.001 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.001 else:
2025-07-02 04:52:33.001 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.001 elif blo < bhi:
2025-07-02 04:52:33.001 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.001
2025-07-02 04:52:33.001 > yield from g
2025-07-02 04:52:33.001
2025-07-02 04:52:33.001 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.001 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.001
2025-07-02 04:52:33.001 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.002 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.002 alo = 326, ahi = 1101
2025-07-02 04:52:33.002 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.002 blo = 326, bhi = 1101
2025-07-02 04:52:33.002
2025-07-02 04:52:33.002 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.002 r"""
2025-07-02 04:52:33.002 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.002 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.002 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.002 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.002
2025-07-02 04:52:33.002 Example:
2025-07-02 04:52:33.002
2025-07-02 04:52:33.002 >>> d = Differ()
2025-07-02 04:52:33.002 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.002 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.003 >>> print(''.join(results), end="")
2025-07-02 04:52:33.003 - abcDefghiJkl
2025-07-02 04:52:33.003 + abcdefGhijkl
2025-07-02 04:52:33.003 """
2025-07-02 04:52:33.003
2025-07-02 04:52:33.003 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.003 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.003 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.003 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.003 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.003
2025-07-02 04:52:33.003 # search for the pair that matches best without being identical
2025-07-02 04:52:33.003 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.003 # on junk -- unless we have to)
2025-07-02 04:52:33.003 for j in range(blo, bhi):
2025-07-02 04:52:33.003 bj = b[j]
2025-07-02 04:52:33.003 cruncher.set_seq2(bj)
2025-07-02 04:52:33.003 for i in range(alo, ahi):
2025-07-02 04:52:33.003 ai = a[i]
2025-07-02 04:52:33.004 if ai == bj:
2025-07-02 04:52:33.004 if eqi is None:
2025-07-02 04:52:33.004 eqi, eqj = i, j
2025-07-02 04:52:33.004 continue
2025-07-02 04:52:33.004 cruncher.set_seq1(ai)
2025-07-02 04:52:33.004 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.004 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.004 # compares by a factor of 3.
2025-07-02 04:52:33.004 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.004 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.004 # of the computation is cached by cruncher
2025-07-02 04:52:33.004 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.004 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.004 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.004 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.004 if best_ratio < cutoff:
2025-07-02 04:52:33.004 # no non-identical "pretty close" pair
2025-07-02 04:52:33.004 if eqi is None:
2025-07-02 04:52:33.004 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.004 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.004 return
2025-07-02 04:52:33.004 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.005 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.005 else:
2025-07-02 04:52:33.005 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.005 eqi = None
2025-07-02 04:52:33.005
2025-07-02 04:52:33.005 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.005 # identical
2025-07-02 04:52:33.005
2025-07-02 04:52:33.005 # pump out diffs from before the synch point
2025-07-02 04:52:33.005 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.005
2025-07-02 04:52:33.005 # do intraline marking on the synch pair
2025-07-02 04:52:33.005 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.005 if eqi is None:
2025-07-02 04:52:33.005 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.005 atags = btags = ""
2025-07-02 04:52:33.005 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.005 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.005 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.005 if tag == 'replace':
2025-07-02 04:52:33.005 atags += '^' * la
2025-07-02 04:52:33.006 btags += '^' * lb
2025-07-02 04:52:33.006 elif tag == 'delete':
2025-07-02 04:52:33.006 atags += '-' * la
2025-07-02 04:52:33.006 elif tag == 'insert':
2025-07-02 04:52:33.006 btags += '+' * lb
2025-07-02 04:52:33.006 elif tag == 'equal':
2025-07-02 04:52:33.006 atags += ' ' * la
2025-07-02 04:52:33.006 btags += ' ' * lb
2025-07-02 04:52:33.006 else:
2025-07-02 04:52:33.006 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.006 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.006 else:
2025-07-02 04:52:33.006 # the synch pair is identical
2025-07-02 04:52:33.006 yield ' ' + aelt
2025-07-02 04:52:33.006
2025-07-02 04:52:33.006 # pump out diffs from after the synch point
2025-07-02 04:52:33.006 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.006
2025-07-02 04:52:33.006 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.006 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.007
2025-07-02 04:52:33.007 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.007 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.007 alo = 327, ahi = 1101
2025-07-02 04:52:33.007 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.007 blo = 327, bhi = 1101
2025-07-02 04:52:33.007
2025-07-02 04:52:33.007 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.007 g = []
2025-07-02 04:52:33.007 if alo < ahi:
2025-07-02 04:52:33.007 if blo < bhi:
2025-07-02 04:52:33.007 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.007 else:
2025-07-02 04:52:33.007 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.007 elif blo < bhi:
2025-07-02 04:52:33.007 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.007
2025-07-02 04:52:33.007 > yield from g
2025-07-02 04:52:33.007
2025-07-02 04:52:33.007 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.008 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.008
2025-07-02 04:52:33.008 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.008 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.008 alo = 327, ahi = 1101
2025-07-02 04:52:33.008 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.008 blo = 327, bhi = 1101
2025-07-02 04:52:33.008
2025-07-02 04:52:33.008 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.008 r"""
2025-07-02 04:52:33.008 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.008 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.008 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.008 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.008
2025-07-02 04:52:33.008 Example:
2025-07-02 04:52:33.008
2025-07-02 04:52:33.008 >>> d = Differ()
2025-07-02 04:52:33.008 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.008 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.008 >>> print(''.join(results), end="")
2025-07-02 04:52:33.009 - abcDefghiJkl
2025-07-02 04:52:33.009 + abcdefGhijkl
2025-07-02 04:52:33.009 """
2025-07-02 04:52:33.009
2025-07-02 04:52:33.009 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.009 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.009 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.009 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.009 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.009
2025-07-02 04:52:33.009 # search for the pair that matches best without being identical
2025-07-02 04:52:33.009 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.009 # on junk -- unless we have to)
2025-07-02 04:52:33.009 for j in range(blo, bhi):
2025-07-02 04:52:33.009 bj = b[j]
2025-07-02 04:52:33.009 cruncher.set_seq2(bj)
2025-07-02 04:52:33.009 for i in range(alo, ahi):
2025-07-02 04:52:33.009 ai = a[i]
2025-07-02 04:52:33.009 if ai == bj:
2025-07-02 04:52:33.010 if eqi is None:
2025-07-02 04:52:33.010 eqi, eqj = i, j
2025-07-02 04:52:33.010 continue
2025-07-02 04:52:33.010 cruncher.set_seq1(ai)
2025-07-02 04:52:33.010 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.010 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.010 # compares by a factor of 3.
2025-07-02 04:52:33.010 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.010 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.010 # of the computation is cached by cruncher
2025-07-02 04:52:33.010 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.010 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.010 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.010 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.010 if best_ratio < cutoff:
2025-07-02 04:52:33.010 # no non-identical "pretty close" pair
2025-07-02 04:52:33.010 if eqi is None:
2025-07-02 04:52:33.010 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.010 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.010 return
2025-07-02 04:52:33.010 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.010 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.011 else:
2025-07-02 04:52:33.011 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.011 eqi = None
2025-07-02 04:52:33.011
2025-07-02 04:52:33.011 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.011 # identical
2025-07-02 04:52:33.011
2025-07-02 04:52:33.011 # pump out diffs from before the synch point
2025-07-02 04:52:33.011 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.011
2025-07-02 04:52:33.011 # do intraline marking on the synch pair
2025-07-02 04:52:33.011 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.011 if eqi is None:
2025-07-02 04:52:33.011 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.011 atags = btags = ""
2025-07-02 04:52:33.011 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.011 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.011 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.011 if tag == 'replace':
2025-07-02 04:52:33.011 atags += '^' * la
2025-07-02 04:52:33.011 btags += '^' * lb
2025-07-02 04:52:33.012 elif tag == 'delete':
2025-07-02 04:52:33.012 atags += '-' * la
2025-07-02 04:52:33.012 elif tag == 'insert':
2025-07-02 04:52:33.012 btags += '+' * lb
2025-07-02 04:52:33.012 elif tag == 'equal':
2025-07-02 04:52:33.012 atags += ' ' * la
2025-07-02 04:52:33.012 btags += ' ' * lb
2025-07-02 04:52:33.012 else:
2025-07-02 04:52:33.012 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.012 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.012 else:
2025-07-02 04:52:33.012 # the synch pair is identical
2025-07-02 04:52:33.012 yield ' ' + aelt
2025-07-02 04:52:33.012
2025-07-02 04:52:33.012 # pump out diffs from after the synch point
2025-07-02 04:52:33.012 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.012
2025-07-02 04:52:33.012 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.012 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.012
2025-07-02 04:52:33.012 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.012 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.013 alo = 328, ahi = 1101
2025-07-02 04:52:33.013 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.013 blo = 328, bhi = 1101
2025-07-02 04:52:33.013
2025-07-02 04:52:33.013 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.013 g = []
2025-07-02 04:52:33.013 if alo < ahi:
2025-07-02 04:52:33.013 if blo < bhi:
2025-07-02 04:52:33.013 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.013 else:
2025-07-02 04:52:33.013 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.013 elif blo < bhi:
2025-07-02 04:52:33.013 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.013
2025-07-02 04:52:33.013 > yield from g
2025-07-02 04:52:33.013
2025-07-02 04:52:33.013 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.013 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.013
2025-07-02 04:52:33.013 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.013 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.014 alo = 328, ahi = 1101
2025-07-02 04:52:33.014 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.014 blo = 328, bhi = 1101
2025-07-02 04:52:33.014
2025-07-02 04:52:33.014 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.014 r"""
2025-07-02 04:52:33.014 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.014 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.014 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.014 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.014
2025-07-02 04:52:33.014 Example:
2025-07-02 04:52:33.014
2025-07-02 04:52:33.014 >>> d = Differ()
2025-07-02 04:52:33.014 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.014 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.014 >>> print(''.join(results), end="")
2025-07-02 04:52:33.014 - abcDefghiJkl
2025-07-02 04:52:33.014 + abcdefGhijkl
2025-07-02 04:52:33.015 """
2025-07-02 04:52:33.015
2025-07-02 04:52:33.015 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.015 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.015 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.015 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.015 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.015
2025-07-02 04:52:33.015 # search for the pair that matches best without being identical
2025-07-02 04:52:33.015 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.015 # on junk -- unless we have to)
2025-07-02 04:52:33.015 for j in range(blo, bhi):
2025-07-02 04:52:33.015 bj = b[j]
2025-07-02 04:52:33.015 cruncher.set_seq2(bj)
2025-07-02 04:52:33.015 for i in range(alo, ahi):
2025-07-02 04:52:33.015 ai = a[i]
2025-07-02 04:52:33.015 if ai == bj:
2025-07-02 04:52:33.015 if eqi is None:
2025-07-02 04:52:33.015 eqi, eqj = i, j
2025-07-02 04:52:33.015 continue
2025-07-02 04:52:33.016 cruncher.set_seq1(ai)
2025-07-02 04:52:33.016 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.016 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.016 # compares by a factor of 3.
2025-07-02 04:52:33.016 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.016 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.016 # of the computation is cached by cruncher
2025-07-02 04:52:33.016 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.016 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.016 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.016 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.016 if best_ratio < cutoff:
2025-07-02 04:52:33.016 # no non-identical "pretty close" pair
2025-07-02 04:52:33.016 if eqi is None:
2025-07-02 04:52:33.016 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.016 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.016 return
2025-07-02 04:52:33.016 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.016 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.016 else:
2025-07-02 04:52:33.016 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.017 eqi = None
2025-07-02 04:52:33.017
2025-07-02 04:52:33.017 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.017 # identical
2025-07-02 04:52:33.017
2025-07-02 04:52:33.017 # pump out diffs from before the synch point
2025-07-02 04:52:33.017 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.017
2025-07-02 04:52:33.017 # do intraline marking on the synch pair
2025-07-02 04:52:33.017 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.017 if eqi is None:
2025-07-02 04:52:33.017 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.017 atags = btags = ""
2025-07-02 04:52:33.017 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.017 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.017 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.017 if tag == 'replace':
2025-07-02 04:52:33.017 atags += '^' * la
2025-07-02 04:52:33.017 btags += '^' * lb
2025-07-02 04:52:33.017 elif tag == 'delete':
2025-07-02 04:52:33.017 atags += '-' * la
2025-07-02 04:52:33.018 elif tag == 'insert':
2025-07-02 04:52:33.018 btags += '+' * lb
2025-07-02 04:52:33.018 elif tag == 'equal':
2025-07-02 04:52:33.018 atags += ' ' * la
2025-07-02 04:52:33.018 btags += ' ' * lb
2025-07-02 04:52:33.018 else:
2025-07-02 04:52:33.018 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.018 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.018 else:
2025-07-02 04:52:33.018 # the synch pair is identical
2025-07-02 04:52:33.018 yield ' ' + aelt
2025-07-02 04:52:33.018
2025-07-02 04:52:33.018 # pump out diffs from after the synch point
2025-07-02 04:52:33.018 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.018
2025-07-02 04:52:33.018 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.018 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.018
2025-07-02 04:52:33.018 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.018 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.019 alo = 329, ahi = 1101
2025-07-02 04:52:33.019 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.019 blo = 329, bhi = 1101
2025-07-02 04:52:33.019
2025-07-02 04:52:33.019 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.019 g = []
2025-07-02 04:52:33.019 if alo < ahi:
2025-07-02 04:52:33.019 if blo < bhi:
2025-07-02 04:52:33.019 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.019 else:
2025-07-02 04:52:33.019 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.019 elif blo < bhi:
2025-07-02 04:52:33.019 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.019
2025-07-02 04:52:33.019 > yield from g
2025-07-02 04:52:33.019
2025-07-02 04:52:33.019 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.019 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.019
2025-07-02 04:52:33.019 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.020 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.020 alo = 329, ahi = 1101
2025-07-02 04:52:33.020 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.020 blo = 329, bhi = 1101
2025-07-02 04:52:33.020
2025-07-02 04:52:33.020 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.020 r"""
2025-07-02 04:52:33.020 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.020 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.020 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.020 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.020
2025-07-02 04:52:33.020 Example:
2025-07-02 04:52:33.020
2025-07-02 04:52:33.020 >>> d = Differ()
2025-07-02 04:52:33.020 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.020 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.020 >>> print(''.join(results), end="")
2025-07-02 04:52:33.020 - abcDefghiJkl
2025-07-02 04:52:33.020 + abcdefGhijkl
2025-07-02 04:52:33.021 """
2025-07-02 04:52:33.021
2025-07-02 04:52:33.021 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.021 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.021 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.021 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.021 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.021
2025-07-02 04:52:33.021 # search for the pair that matches best without being identical
2025-07-02 04:52:33.021 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.021 # on junk -- unless we have to)
2025-07-02 04:52:33.021 for j in range(blo, bhi):
2025-07-02 04:52:33.021 bj = b[j]
2025-07-02 04:52:33.021 cruncher.set_seq2(bj)
2025-07-02 04:52:33.021 for i in range(alo, ahi):
2025-07-02 04:52:33.021 ai = a[i]
2025-07-02 04:52:33.021 if ai == bj:
2025-07-02 04:52:33.021 if eqi is None:
2025-07-02 04:52:33.021 eqi, eqj = i, j
2025-07-02 04:52:33.021 continue
2025-07-02 04:52:33.021 cruncher.set_seq1(ai)
2025-07-02 04:52:33.022 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.022 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.022 # compares by a factor of 3.
2025-07-02 04:52:33.022 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.022 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.022 # of the computation is cached by cruncher
2025-07-02 04:52:33.022 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.022 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.022 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.022 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.022 if best_ratio < cutoff:
2025-07-02 04:52:33.022 # no non-identical "pretty close" pair
2025-07-02 04:52:33.022 if eqi is None:
2025-07-02 04:52:33.022 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.022 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.022 return
2025-07-02 04:52:33.022 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.022 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.022 else:
2025-07-02 04:52:33.022 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.022 eqi = None
2025-07-02 04:52:33.023
2025-07-02 04:52:33.023 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.023 # identical
2025-07-02 04:52:33.023
2025-07-02 04:52:33.023 # pump out diffs from before the synch point
2025-07-02 04:52:33.023 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.023
2025-07-02 04:52:33.023 # do intraline marking on the synch pair
2025-07-02 04:52:33.023 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.023 if eqi is None:
2025-07-02 04:52:33.023 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.023 atags = btags = ""
2025-07-02 04:52:33.023 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.023 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.023 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.023 if tag == 'replace':
2025-07-02 04:52:33.023 atags += '^' * la
2025-07-02 04:52:33.023 btags += '^' * lb
2025-07-02 04:52:33.023 elif tag == 'delete':
2025-07-02 04:52:33.023 atags += '-' * la
2025-07-02 04:52:33.024 elif tag == 'insert':
2025-07-02 04:52:33.024 btags += '+' * lb
2025-07-02 04:52:33.024 elif tag == 'equal':
2025-07-02 04:52:33.024 atags += ' ' * la
2025-07-02 04:52:33.024 btags += ' ' * lb
2025-07-02 04:52:33.024 else:
2025-07-02 04:52:33.024 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.024 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.024 else:
2025-07-02 04:52:33.024 # the synch pair is identical
2025-07-02 04:52:33.024 yield ' ' + aelt
2025-07-02 04:52:33.024
2025-07-02 04:52:33.024 # pump out diffs from after the synch point
2025-07-02 04:52:33.024 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.024
2025-07-02 04:52:33.024 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.024 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.024
2025-07-02 04:52:33.024 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.024 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.024 alo = 330, ahi = 1101
2025-07-02 04:52:33.025 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.025 blo = 330, bhi = 1101
2025-07-02 04:52:33.025
2025-07-02 04:52:33.025 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.025 g = []
2025-07-02 04:52:33.025 if alo < ahi:
2025-07-02 04:52:33.025 if blo < bhi:
2025-07-02 04:52:33.025 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.025 else:
2025-07-02 04:52:33.025 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.025 elif blo < bhi:
2025-07-02 04:52:33.025 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.025
2025-07-02 04:52:33.025 > yield from g
2025-07-02 04:52:33.025
2025-07-02 04:52:33.025 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.025 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.025
2025-07-02 04:52:33.025 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.025 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.025 alo = 330, ahi = 1101
2025-07-02 04:52:33.026 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.026 blo = 330, bhi = 1101
2025-07-02 04:52:33.026
2025-07-02 04:52:33.026 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.026 r"""
2025-07-02 04:52:33.026 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.026 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.026 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.026 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.026
2025-07-02 04:52:33.026 Example:
2025-07-02 04:52:33.026
2025-07-02 04:52:33.026 >>> d = Differ()
2025-07-02 04:52:33.026 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.026 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.026 >>> print(''.join(results), end="")
2025-07-02 04:52:33.026 - abcDefghiJkl
2025-07-02 04:52:33.026 + abcdefGhijkl
2025-07-02 04:52:33.026 """
2025-07-02 04:52:33.026
2025-07-02 04:52:33.027 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.027 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.027 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.027 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.027 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.027
2025-07-02 04:52:33.027 # search for the pair that matches best without being identical
2025-07-02 04:52:33.027 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.027 # on junk -- unless we have to)
2025-07-02 04:52:33.027 for j in range(blo, bhi):
2025-07-02 04:52:33.027 bj = b[j]
2025-07-02 04:52:33.027 cruncher.set_seq2(bj)
2025-07-02 04:52:33.027 for i in range(alo, ahi):
2025-07-02 04:52:33.027 ai = a[i]
2025-07-02 04:52:33.027 if ai == bj:
2025-07-02 04:52:33.027 if eqi is None:
2025-07-02 04:52:33.027 eqi, eqj = i, j
2025-07-02 04:52:33.027 continue
2025-07-02 04:52:33.027 cruncher.set_seq1(ai)
2025-07-02 04:52:33.027 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.028 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.028 # compares by a factor of 3.
2025-07-02 04:52:33.028 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.028 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.028 # of the computation is cached by cruncher
2025-07-02 04:52:33.028 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.028 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.028 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.028 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.028 if best_ratio < cutoff:
2025-07-02 04:52:33.028 # no non-identical "pretty close" pair
2025-07-02 04:52:33.028 if eqi is None:
2025-07-02 04:52:33.028 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.028 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.028 return
2025-07-02 04:52:33.028 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.028 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.028 else:
2025-07-02 04:52:33.028 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.029 eqi = None
2025-07-02 04:52:33.029
2025-07-02 04:52:33.029 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.029 # identical
2025-07-02 04:52:33.029
2025-07-02 04:52:33.029 # pump out diffs from before the synch point
2025-07-02 04:52:33.029 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.029
2025-07-02 04:52:33.029 # do intraline marking on the synch pair
2025-07-02 04:52:33.029 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.029 if eqi is None:
2025-07-02 04:52:33.029 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.029 atags = btags = ""
2025-07-02 04:52:33.029 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.029 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.029 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.029 if tag == 'replace':
2025-07-02 04:52:33.029 atags += '^' * la
2025-07-02 04:52:33.029 btags += '^' * lb
2025-07-02 04:52:33.029 elif tag == 'delete':
2025-07-02 04:52:33.029 atags += '-' * la
2025-07-02 04:52:33.030 elif tag == 'insert':
2025-07-02 04:52:33.030 btags += '+' * lb
2025-07-02 04:52:33.030 elif tag == 'equal':
2025-07-02 04:52:33.030 atags += ' ' * la
2025-07-02 04:52:33.030 btags += ' ' * lb
2025-07-02 04:52:33.030 else:
2025-07-02 04:52:33.030 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.030 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.030 else:
2025-07-02 04:52:33.030 # the synch pair is identical
2025-07-02 04:52:33.030 yield ' ' + aelt
2025-07-02 04:52:33.030
2025-07-02 04:52:33.030 # pump out diffs from after the synch point
2025-07-02 04:52:33.030 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.030
2025-07-02 04:52:33.030 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.030 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.030
2025-07-02 04:52:33.030 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.030 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.030 alo = 331, ahi = 1101
2025-07-02 04:52:33.030 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.031 blo = 331, bhi = 1101
2025-07-02 04:52:33.031
2025-07-02 04:52:33.031 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.031 g = []
2025-07-02 04:52:33.031 if alo < ahi:
2025-07-02 04:52:33.031 if blo < bhi:
2025-07-02 04:52:33.031 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.031 else:
2025-07-02 04:52:33.031 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.031 elif blo < bhi:
2025-07-02 04:52:33.031 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.031
2025-07-02 04:52:33.031 > yield from g
2025-07-02 04:52:33.031
2025-07-02 04:52:33.031 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.031 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.031
2025-07-02 04:52:33.031 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.031 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.032 alo = 331, ahi = 1101
2025-07-02 04:52:33.032 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.032 blo = 331, bhi = 1101
2025-07-02 04:52:33.032
2025-07-02 04:52:33.032 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.032 r"""
2025-07-02 04:52:33.032 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.032 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.032 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.032 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.032
2025-07-02 04:52:33.032 Example:
2025-07-02 04:52:33.032
2025-07-02 04:52:33.032 >>> d = Differ()
2025-07-02 04:52:33.032 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.032 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.032 >>> print(''.join(results), end="")
2025-07-02 04:52:33.032 - abcDefghiJkl
2025-07-02 04:52:33.032 + abcdefGhijkl
2025-07-02 04:52:33.033 """
2025-07-02 04:52:33.033
2025-07-02 04:52:33.033 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.033 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.033 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.033 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.033 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.033
2025-07-02 04:52:33.033 # search for the pair that matches best without being identical
2025-07-02 04:52:33.033 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.033 # on junk -- unless we have to)
2025-07-02 04:52:33.033 for j in range(blo, bhi):
2025-07-02 04:52:33.033 bj = b[j]
2025-07-02 04:52:33.033 cruncher.set_seq2(bj)
2025-07-02 04:52:33.033 for i in range(alo, ahi):
2025-07-02 04:52:33.033 ai = a[i]
2025-07-02 04:52:33.033 if ai == bj:
2025-07-02 04:52:33.033 if eqi is None:
2025-07-02 04:52:33.033 eqi, eqj = i, j
2025-07-02 04:52:33.033 continue
2025-07-02 04:52:33.033 cruncher.set_seq1(ai)
2025-07-02 04:52:33.034 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.034 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.034 # compares by a factor of 3.
2025-07-02 04:52:33.034 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.034 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.034 # of the computation is cached by cruncher
2025-07-02 04:52:33.034 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.034 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.034 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.034 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.034 if best_ratio < cutoff:
2025-07-02 04:52:33.034 # no non-identical "pretty close" pair
2025-07-02 04:52:33.034 if eqi is None:
2025-07-02 04:52:33.034 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.034 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.034 return
2025-07-02 04:52:33.034 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.034 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.035 else:
2025-07-02 04:52:33.035 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.035 eqi = None
2025-07-02 04:52:33.035
2025-07-02 04:52:33.035 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.035 # identical
2025-07-02 04:52:33.035
2025-07-02 04:52:33.035 # pump out diffs from before the synch point
2025-07-02 04:52:33.035 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.035
2025-07-02 04:52:33.035 # do intraline marking on the synch pair
2025-07-02 04:52:33.035 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.035 if eqi is None:
2025-07-02 04:52:33.035 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.035 atags = btags = ""
2025-07-02 04:52:33.035 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.035 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.035 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.035 if tag == 'replace':
2025-07-02 04:52:33.035 atags += '^' * la
2025-07-02 04:52:33.036 btags += '^' * lb
2025-07-02 04:52:33.036 elif tag == 'delete':
2025-07-02 04:52:33.036 atags += '-' * la
2025-07-02 04:52:33.036 elif tag == 'insert':
2025-07-02 04:52:33.036 btags += '+' * lb
2025-07-02 04:52:33.036 elif tag == 'equal':
2025-07-02 04:52:33.036 atags += ' ' * la
2025-07-02 04:52:33.036 btags += ' ' * lb
2025-07-02 04:52:33.036 else:
2025-07-02 04:52:33.036 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.036 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.036 else:
2025-07-02 04:52:33.036 # the synch pair is identical
2025-07-02 04:52:33.036 yield ' ' + aelt
2025-07-02 04:52:33.036
2025-07-02 04:52:33.036 # pump out diffs from after the synch point
2025-07-02 04:52:33.036 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.036
2025-07-02 04:52:33.036 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.036 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.036
2025-07-02 04:52:33.037 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.037 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.037 alo = 334, ahi = 1101
2025-07-02 04:52:33.037 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.037 blo = 334, bhi = 1101
2025-07-02 04:52:33.037
2025-07-02 04:52:33.037 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.037 g = []
2025-07-02 04:52:33.037 if alo < ahi:
2025-07-02 04:52:33.037 if blo < bhi:
2025-07-02 04:52:33.037 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.037 else:
2025-07-02 04:52:33.037 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.037 elif blo < bhi:
2025-07-02 04:52:33.037 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.037
2025-07-02 04:52:33.037 > yield from g
2025-07-02 04:52:33.037
2025-07-02 04:52:33.037 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.037 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.037
2025-07-02 04:52:33.037 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.038 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.038 alo = 334, ahi = 1101
2025-07-02 04:52:33.038 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.038 blo = 334, bhi = 1101
2025-07-02 04:52:33.038
2025-07-02 04:52:33.038 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.038 r"""
2025-07-02 04:52:33.038 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.038 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.038 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.038 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.038
2025-07-02 04:52:33.038 Example:
2025-07-02 04:52:33.038
2025-07-02 04:52:33.038 >>> d = Differ()
2025-07-02 04:52:33.038 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.038 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.038 >>> print(''.join(results), end="")
2025-07-02 04:52:33.038 - abcDefghiJkl
2025-07-02 04:52:33.039 + abcdefGhijkl
2025-07-02 04:52:33.039 """
2025-07-02 04:52:33.039
2025-07-02 04:52:33.039 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.039 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.039 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.039 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.039 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.039
2025-07-02 04:52:33.039 # search for the pair that matches best without being identical
2025-07-02 04:52:33.039 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.039 # on junk -- unless we have to)
2025-07-02 04:52:33.039 for j in range(blo, bhi):
2025-07-02 04:52:33.039 bj = b[j]
2025-07-02 04:52:33.039 cruncher.set_seq2(bj)
2025-07-02 04:52:33.039 for i in range(alo, ahi):
2025-07-02 04:52:33.039 ai = a[i]
2025-07-02 04:52:33.039 if ai == bj:
2025-07-02 04:52:33.039 if eqi is None:
2025-07-02 04:52:33.040 eqi, eqj = i, j
2025-07-02 04:52:33.040 continue
2025-07-02 04:52:33.040 cruncher.set_seq1(ai)
2025-07-02 04:52:33.040 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.040 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.040 # compares by a factor of 3.
2025-07-02 04:52:33.040 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.040 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.040 # of the computation is cached by cruncher
2025-07-02 04:52:33.040 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.040 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.040 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.040 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.040 if best_ratio < cutoff:
2025-07-02 04:52:33.040 # no non-identical "pretty close" pair
2025-07-02 04:52:33.040 if eqi is None:
2025-07-02 04:52:33.040 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.040 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.040 return
2025-07-02 04:52:33.040 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.041 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.041 else:
2025-07-02 04:52:33.041 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.041 eqi = None
2025-07-02 04:52:33.041
2025-07-02 04:52:33.041 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.041 # identical
2025-07-02 04:52:33.041
2025-07-02 04:52:33.041 # pump out diffs from before the synch point
2025-07-02 04:52:33.041 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.041
2025-07-02 04:52:33.041 # do intraline marking on the synch pair
2025-07-02 04:52:33.041 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.041 if eqi is None:
2025-07-02 04:52:33.041 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.041 atags = btags = ""
2025-07-02 04:52:33.041 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.041 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.041 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.041 if tag == 'replace':
2025-07-02 04:52:33.041 atags += '^' * la
2025-07-02 04:52:33.042 btags += '^' * lb
2025-07-02 04:52:33.042 elif tag == 'delete':
2025-07-02 04:52:33.042 atags += '-' * la
2025-07-02 04:52:33.042 elif tag == 'insert':
2025-07-02 04:52:33.042 btags += '+' * lb
2025-07-02 04:52:33.042 elif tag == 'equal':
2025-07-02 04:52:33.042 atags += ' ' * la
2025-07-02 04:52:33.042 btags += ' ' * lb
2025-07-02 04:52:33.042 else:
2025-07-02 04:52:33.042 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.042 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.042 else:
2025-07-02 04:52:33.042 # the synch pair is identical
2025-07-02 04:52:33.042 yield ' ' + aelt
2025-07-02 04:52:33.042
2025-07-02 04:52:33.042 # pump out diffs from after the synch point
2025-07-02 04:52:33.042 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.042
2025-07-02 04:52:33.042 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.042 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.042
2025-07-02 04:52:33.043 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.043 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.043 alo = 335, ahi = 1101
2025-07-02 04:52:33.043 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.043 blo = 335, bhi = 1101
2025-07-02 04:52:33.043
2025-07-02 04:52:33.043 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.043 g = []
2025-07-02 04:52:33.043 if alo < ahi:
2025-07-02 04:52:33.043 if blo < bhi:
2025-07-02 04:52:33.043 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.043 else:
2025-07-02 04:52:33.043 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.043 elif blo < bhi:
2025-07-02 04:52:33.043 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.043
2025-07-02 04:52:33.043 > yield from g
2025-07-02 04:52:33.043
2025-07-02 04:52:33.043 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.043 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.044
2025-07-02 04:52:33.044 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.044 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.044 alo = 335, ahi = 1101
2025-07-02 04:52:33.044 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.044 blo = 335, bhi = 1101
2025-07-02 04:52:33.044
2025-07-02 04:52:33.044 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.044 r"""
2025-07-02 04:52:33.044 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.044 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.044 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.044 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.044
2025-07-02 04:52:33.044 Example:
2025-07-02 04:52:33.044
2025-07-02 04:52:33.044 >>> d = Differ()
2025-07-02 04:52:33.044 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.044 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.044 >>> print(''.join(results), end="")
2025-07-02 04:52:33.045 - abcDefghiJkl
2025-07-02 04:52:33.045 + abcdefGhijkl
2025-07-02 04:52:33.045 """
2025-07-02 04:52:33.045
2025-07-02 04:52:33.045 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.045 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.045 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.045 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.045 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.045
2025-07-02 04:52:33.045 # search for the pair that matches best without being identical
2025-07-02 04:52:33.045 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.045 # on junk -- unless we have to)
2025-07-02 04:52:33.045 for j in range(blo, bhi):
2025-07-02 04:52:33.045 bj = b[j]
2025-07-02 04:52:33.045 cruncher.set_seq2(bj)
2025-07-02 04:52:33.045 for i in range(alo, ahi):
2025-07-02 04:52:33.045 ai = a[i]
2025-07-02 04:52:33.045 if ai == bj:
2025-07-02 04:52:33.045 if eqi is None:
2025-07-02 04:52:33.046 eqi, eqj = i, j
2025-07-02 04:52:33.046 continue
2025-07-02 04:52:33.046 cruncher.set_seq1(ai)
2025-07-02 04:52:33.046 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.046 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.046 # compares by a factor of 3.
2025-07-02 04:52:33.046 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.046 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.046 # of the computation is cached by cruncher
2025-07-02 04:52:33.046 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.046 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.046 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.046 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.046 if best_ratio < cutoff:
2025-07-02 04:52:33.046 # no non-identical "pretty close" pair
2025-07-02 04:52:33.046 if eqi is None:
2025-07-02 04:52:33.046 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.046 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.046 return
2025-07-02 04:52:33.046 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.046 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.047 else:
2025-07-02 04:52:33.047 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.047 eqi = None
2025-07-02 04:52:33.047
2025-07-02 04:52:33.047 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.047 # identical
2025-07-02 04:52:33.047
2025-07-02 04:52:33.047 # pump out diffs from before the synch point
2025-07-02 04:52:33.047 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.047
2025-07-02 04:52:33.047 # do intraline marking on the synch pair
2025-07-02 04:52:33.047 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.047 if eqi is None:
2025-07-02 04:52:33.047 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.047 atags = btags = ""
2025-07-02 04:52:33.047 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.047 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.047 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.047 if tag == 'replace':
2025-07-02 04:52:33.047 atags += '^' * la
2025-07-02 04:52:33.047 btags += '^' * lb
2025-07-02 04:52:33.047 elif tag == 'delete':
2025-07-02 04:52:33.048 atags += '-' * la
2025-07-02 04:52:33.048 elif tag == 'insert':
2025-07-02 04:52:33.048 btags += '+' * lb
2025-07-02 04:52:33.048 elif tag == 'equal':
2025-07-02 04:52:33.048 atags += ' ' * la
2025-07-02 04:52:33.048 btags += ' ' * lb
2025-07-02 04:52:33.048 else:
2025-07-02 04:52:33.048 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.048 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.048 else:
2025-07-02 04:52:33.048 # the synch pair is identical
2025-07-02 04:52:33.048 yield ' ' + aelt
2025-07-02 04:52:33.048
2025-07-02 04:52:33.048 # pump out diffs from after the synch point
2025-07-02 04:52:33.048 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.048
2025-07-02 04:52:33.048 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.048 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.048
2025-07-02 04:52:33.049 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.049 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.049 alo = 336, ahi = 1101
2025-07-02 04:52:33.049 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.049 blo = 336, bhi = 1101
2025-07-02 04:52:33.049
2025-07-02 04:52:33.049 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.049 g = []
2025-07-02 04:52:33.049 if alo < ahi:
2025-07-02 04:52:33.049 if blo < bhi:
2025-07-02 04:52:33.049 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.049 else:
2025-07-02 04:52:33.049 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.049 elif blo < bhi:
2025-07-02 04:52:33.049 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.049
2025-07-02 04:52:33.049 > yield from g
2025-07-02 04:52:33.049
2025-07-02 04:52:33.049 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.049 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.050
2025-07-02 04:52:33.050 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.050 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.050 alo = 336, ahi = 1101
2025-07-02 04:52:33.050 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.050 blo = 336, bhi = 1101
2025-07-02 04:52:33.050
2025-07-02 04:52:33.050 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.050 r"""
2025-07-02 04:52:33.050 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.050 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.050 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.050 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.050
2025-07-02 04:52:33.050 Example:
2025-07-02 04:52:33.050
2025-07-02 04:52:33.050 >>> d = Differ()
2025-07-02 04:52:33.050 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.050 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.051 >>> print(''.join(results), end="")
2025-07-02 04:52:33.051 - abcDefghiJkl
2025-07-02 04:52:33.051 + abcdefGhijkl
2025-07-02 04:52:33.051 """
2025-07-02 04:52:33.051
2025-07-02 04:52:33.051 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.051 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.051 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.051 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.051 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.051
2025-07-02 04:52:33.051 # search for the pair that matches best without being identical
2025-07-02 04:52:33.051 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.051 # on junk -- unless we have to)
2025-07-02 04:52:33.051 for j in range(blo, bhi):
2025-07-02 04:52:33.051 bj = b[j]
2025-07-02 04:52:33.051 cruncher.set_seq2(bj)
2025-07-02 04:52:33.051 for i in range(alo, ahi):
2025-07-02 04:52:33.051 ai = a[i]
2025-07-02 04:52:33.051 if ai == bj:
2025-07-02 04:52:33.052 if eqi is None:
2025-07-02 04:52:33.052 eqi, eqj = i, j
2025-07-02 04:52:33.052 continue
2025-07-02 04:52:33.052 cruncher.set_seq1(ai)
2025-07-02 04:52:33.052 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.052 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.052 # compares by a factor of 3.
2025-07-02 04:52:33.052 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.052 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.052 # of the computation is cached by cruncher
2025-07-02 04:52:33.052 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.052 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.052 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.052 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.052 if best_ratio < cutoff:
2025-07-02 04:52:33.052 # no non-identical "pretty close" pair
2025-07-02 04:52:33.052 if eqi is None:
2025-07-02 04:52:33.052 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.052 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.052 return
2025-07-02 04:52:33.052 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.053 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.053 else:
2025-07-02 04:52:33.053 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.053 eqi = None
2025-07-02 04:52:33.053
2025-07-02 04:52:33.053 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.053 # identical
2025-07-02 04:52:33.053
2025-07-02 04:52:33.053 # pump out diffs from before the synch point
2025-07-02 04:52:33.053 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.053
2025-07-02 04:52:33.053 # do intraline marking on the synch pair
2025-07-02 04:52:33.053 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.053 if eqi is None:
2025-07-02 04:52:33.053 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.053 atags = btags = ""
2025-07-02 04:52:33.053 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.053 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.053 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.053 if tag == 'replace':
2025-07-02 04:52:33.053 atags += '^' * la
2025-07-02 04:52:33.054 btags += '^' * lb
2025-07-02 04:52:33.054 elif tag == 'delete':
2025-07-02 04:52:33.054 atags += '-' * la
2025-07-02 04:52:33.054 elif tag == 'insert':
2025-07-02 04:52:33.054 btags += '+' * lb
2025-07-02 04:52:33.054 elif tag == 'equal':
2025-07-02 04:52:33.054 atags += ' ' * la
2025-07-02 04:52:33.054 btags += ' ' * lb
2025-07-02 04:52:33.054 else:
2025-07-02 04:52:33.054 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.054 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.054 else:
2025-07-02 04:52:33.054 # the synch pair is identical
2025-07-02 04:52:33.054 yield ' ' + aelt
2025-07-02 04:52:33.054
2025-07-02 04:52:33.054 # pump out diffs from after the synch point
2025-07-02 04:52:33.054 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.054
2025-07-02 04:52:33.054 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.054 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.054
2025-07-02 04:52:33.054 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.055 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.055 alo = 337, ahi = 1101
2025-07-02 04:52:33.055 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.055 blo = 337, bhi = 1101
2025-07-02 04:52:33.055
2025-07-02 04:52:33.055 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.055 g = []
2025-07-02 04:52:33.055 if alo < ahi:
2025-07-02 04:52:33.055 if blo < bhi:
2025-07-02 04:52:33.055 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.055 else:
2025-07-02 04:52:33.055 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.055 elif blo < bhi:
2025-07-02 04:52:33.055 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.055
2025-07-02 04:52:33.055 > yield from g
2025-07-02 04:52:33.055
2025-07-02 04:52:33.055 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.055 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.055
2025-07-02 04:52:33.055 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.056 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.056 alo = 337, ahi = 1101
2025-07-02 04:52:33.056 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.056 blo = 337, bhi = 1101
2025-07-02 04:52:33.056
2025-07-02 04:52:33.056 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.056 r"""
2025-07-02 04:52:33.056 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.056 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.056 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.056 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.056
2025-07-02 04:52:33.056 Example:
2025-07-02 04:52:33.056
2025-07-02 04:52:33.056 >>> d = Differ()
2025-07-02 04:52:33.056 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.056 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.056 >>> print(''.join(results), end="")
2025-07-02 04:52:33.056 - abcDefghiJkl
2025-07-02 04:52:33.057 + abcdefGhijkl
2025-07-02 04:52:33.057 """
2025-07-02 04:52:33.057
2025-07-02 04:52:33.057 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.057 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.057 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.057 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.057 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.057
2025-07-02 04:52:33.057 # search for the pair that matches best without being identical
2025-07-02 04:52:33.057 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.057 # on junk -- unless we have to)
2025-07-02 04:52:33.057 for j in range(blo, bhi):
2025-07-02 04:52:33.057 bj = b[j]
2025-07-02 04:52:33.057 cruncher.set_seq2(bj)
2025-07-02 04:52:33.057 for i in range(alo, ahi):
2025-07-02 04:52:33.057 ai = a[i]
2025-07-02 04:52:33.057 if ai == bj:
2025-07-02 04:52:33.057 if eqi is None:
2025-07-02 04:52:33.058 eqi, eqj = i, j
2025-07-02 04:52:33.058 continue
2025-07-02 04:52:33.058 cruncher.set_seq1(ai)
2025-07-02 04:52:33.058 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.058 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.058 # compares by a factor of 3.
2025-07-02 04:52:33.058 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.058 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.058 # of the computation is cached by cruncher
2025-07-02 04:52:33.058 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.058 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.058 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.058 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.058 if best_ratio < cutoff:
2025-07-02 04:52:33.058 # no non-identical "pretty close" pair
2025-07-02 04:52:33.058 if eqi is None:
2025-07-02 04:52:33.058 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.058 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.058 return
2025-07-02 04:52:33.058 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.059 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.059 else:
2025-07-02 04:52:33.059 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.059 eqi = None
2025-07-02 04:52:33.059
2025-07-02 04:52:33.059 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.059 # identical
2025-07-02 04:52:33.059
2025-07-02 04:52:33.059 # pump out diffs from before the synch point
2025-07-02 04:52:33.059 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.059
2025-07-02 04:52:33.059 # do intraline marking on the synch pair
2025-07-02 04:52:33.059 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.059 if eqi is None:
2025-07-02 04:52:33.059 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.059 atags = btags = ""
2025-07-02 04:52:33.059 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.059 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.059 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.059 if tag == 'replace':
2025-07-02 04:52:33.059 atags += '^' * la
2025-07-02 04:52:33.059 btags += '^' * lb
2025-07-02 04:52:33.060 elif tag == 'delete':
2025-07-02 04:52:33.060 atags += '-' * la
2025-07-02 04:52:33.060 elif tag == 'insert':
2025-07-02 04:52:33.060 btags += '+' * lb
2025-07-02 04:52:33.060 elif tag == 'equal':
2025-07-02 04:52:33.060 atags += ' ' * la
2025-07-02 04:52:33.060 btags += ' ' * lb
2025-07-02 04:52:33.060 else:
2025-07-02 04:52:33.060 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.060 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.060 else:
2025-07-02 04:52:33.060 # the synch pair is identical
2025-07-02 04:52:33.060 yield ' ' + aelt
2025-07-02 04:52:33.060
2025-07-02 04:52:33.060 # pump out diffs from after the synch point
2025-07-02 04:52:33.060 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.060
2025-07-02 04:52:33.060 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.060 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.060
2025-07-02 04:52:33.060 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.060 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.061 alo = 338, ahi = 1101
2025-07-02 04:52:33.061 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.061 blo = 338, bhi = 1101
2025-07-02 04:52:33.061
2025-07-02 04:52:33.061 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.061 g = []
2025-07-02 04:52:33.061 if alo < ahi:
2025-07-02 04:52:33.061 if blo < bhi:
2025-07-02 04:52:33.061 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.061 else:
2025-07-02 04:52:33.061 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.061 elif blo < bhi:
2025-07-02 04:52:33.061 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.061
2025-07-02 04:52:33.061 > yield from g
2025-07-02 04:52:33.061
2025-07-02 04:52:33.061 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.061 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.061
2025-07-02 04:52:33.061 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.061 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.062 alo = 338, ahi = 1101
2025-07-02 04:52:33.062 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.062 blo = 338, bhi = 1101
2025-07-02 04:52:33.062
2025-07-02 04:52:33.062 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.062 r"""
2025-07-02 04:52:33.062 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.062 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.062 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.062 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.062
2025-07-02 04:52:33.062 Example:
2025-07-02 04:52:33.062
2025-07-02 04:52:33.062 >>> d = Differ()
2025-07-02 04:52:33.062 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.062 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.062 >>> print(''.join(results), end="")
2025-07-02 04:52:33.062 - abcDefghiJkl
2025-07-02 04:52:33.062 + abcdefGhijkl
2025-07-02 04:52:33.063 """
2025-07-02 04:52:33.063
2025-07-02 04:52:33.063 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.063 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.063 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.063 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.063 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.063
2025-07-02 04:52:33.063 # search for the pair that matches best without being identical
2025-07-02 04:52:33.063 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.063 # on junk -- unless we have to)
2025-07-02 04:52:33.063 for j in range(blo, bhi):
2025-07-02 04:52:33.063 bj = b[j]
2025-07-02 04:52:33.063 cruncher.set_seq2(bj)
2025-07-02 04:52:33.063 for i in range(alo, ahi):
2025-07-02 04:52:33.063 ai = a[i]
2025-07-02 04:52:33.063 if ai == bj:
2025-07-02 04:52:33.063 if eqi is None:
2025-07-02 04:52:33.063 eqi, eqj = i, j
2025-07-02 04:52:33.063 continue
2025-07-02 04:52:33.063 cruncher.set_seq1(ai)
2025-07-02 04:52:33.063 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.064 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.064 # compares by a factor of 3.
2025-07-02 04:52:33.064 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.064 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.064 # of the computation is cached by cruncher
2025-07-02 04:52:33.064 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.064 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.064 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.064 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.064 if best_ratio < cutoff:
2025-07-02 04:52:33.064 # no non-identical "pretty close" pair
2025-07-02 04:52:33.064 if eqi is None:
2025-07-02 04:52:33.064 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.064 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.064 return
2025-07-02 04:52:33.064 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.064 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.064 else:
2025-07-02 04:52:33.064 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.065 eqi = None
2025-07-02 04:52:33.065
2025-07-02 04:52:33.065 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.065 # identical
2025-07-02 04:52:33.065
2025-07-02 04:52:33.065 # pump out diffs from before the synch point
2025-07-02 04:52:33.065 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.065
2025-07-02 04:52:33.065 # do intraline marking on the synch pair
2025-07-02 04:52:33.065 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.065 if eqi is None:
2025-07-02 04:52:33.065 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.065 atags = btags = ""
2025-07-02 04:52:33.065 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.065 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.065 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.065 if tag == 'replace':
2025-07-02 04:52:33.065 atags += '^' * la
2025-07-02 04:52:33.065 btags += '^' * lb
2025-07-02 04:52:33.065 elif tag == 'delete':
2025-07-02 04:52:33.065 atags += '-' * la
2025-07-02 04:52:33.066 elif tag == 'insert':
2025-07-02 04:52:33.066 btags += '+' * lb
2025-07-02 04:52:33.066 elif tag == 'equal':
2025-07-02 04:52:33.066 atags += ' ' * la
2025-07-02 04:52:33.066 btags += ' ' * lb
2025-07-02 04:52:33.066 else:
2025-07-02 04:52:33.066 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.066 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.066 else:
2025-07-02 04:52:33.066 # the synch pair is identical
2025-07-02 04:52:33.066 yield ' ' + aelt
2025-07-02 04:52:33.066
2025-07-02 04:52:33.066 # pump out diffs from after the synch point
2025-07-02 04:52:33.066 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.066
2025-07-02 04:52:33.066 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.066 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.066
2025-07-02 04:52:33.066 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.066 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.067 alo = 339, ahi = 1101
2025-07-02 04:52:33.067 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.067 blo = 339, bhi = 1101
2025-07-02 04:52:33.067
2025-07-02 04:52:33.067 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.067 g = []
2025-07-02 04:52:33.067 if alo < ahi:
2025-07-02 04:52:33.067 if blo < bhi:
2025-07-02 04:52:33.067 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.067 else:
2025-07-02 04:52:33.067 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.067 elif blo < bhi:
2025-07-02 04:52:33.067 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.067
2025-07-02 04:52:33.067 > yield from g
2025-07-02 04:52:33.067
2025-07-02 04:52:33.067 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.067 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.067
2025-07-02 04:52:33.067 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.067 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.068 alo = 339, ahi = 1101
2025-07-02 04:52:33.068 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.068 blo = 339, bhi = 1101
2025-07-02 04:52:33.068
2025-07-02 04:52:33.068 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.068 r"""
2025-07-02 04:52:33.068 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.068 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.068 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.068 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.068
2025-07-02 04:52:33.068 Example:
2025-07-02 04:52:33.068
2025-07-02 04:52:33.068 >>> d = Differ()
2025-07-02 04:52:33.068 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.068 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.068 >>> print(''.join(results), end="")
2025-07-02 04:52:33.068 - abcDefghiJkl
2025-07-02 04:52:33.068 + abcdefGhijkl
2025-07-02 04:52:33.069 """
2025-07-02 04:52:33.069
2025-07-02 04:52:33.069 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.069 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.069 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.069 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.069 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.069
2025-07-02 04:52:33.069 # search for the pair that matches best without being identical
2025-07-02 04:52:33.069 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.069 # on junk -- unless we have to)
2025-07-02 04:52:33.069 for j in range(blo, bhi):
2025-07-02 04:52:33.069 bj = b[j]
2025-07-02 04:52:33.069 cruncher.set_seq2(bj)
2025-07-02 04:52:33.069 for i in range(alo, ahi):
2025-07-02 04:52:33.069 ai = a[i]
2025-07-02 04:52:33.069 if ai == bj:
2025-07-02 04:52:33.069 if eqi is None:
2025-07-02 04:52:33.069 eqi, eqj = i, j
2025-07-02 04:52:33.069 continue
2025-07-02 04:52:33.069 cruncher.set_seq1(ai)
2025-07-02 04:52:33.069 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.070 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.070 # compares by a factor of 3.
2025-07-02 04:52:33.070 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.070 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.070 # of the computation is cached by cruncher
2025-07-02 04:52:33.070 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.070 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.070 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.070 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.070 if best_ratio < cutoff:
2025-07-02 04:52:33.070 # no non-identical "pretty close" pair
2025-07-02 04:52:33.070 if eqi is None:
2025-07-02 04:52:33.070 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.070 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.070 return
2025-07-02 04:52:33.070 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.070 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.070 else:
2025-07-02 04:52:33.070 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.070 eqi = None
2025-07-02 04:52:33.070
2025-07-02 04:52:33.071 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.071 # identical
2025-07-02 04:52:33.071
2025-07-02 04:52:33.071 # pump out diffs from before the synch point
2025-07-02 04:52:33.071 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.071
2025-07-02 04:52:33.071 # do intraline marking on the synch pair
2025-07-02 04:52:33.071 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.071 if eqi is None:
2025-07-02 04:52:33.071 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.071 atags = btags = ""
2025-07-02 04:52:33.071 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.071 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.071 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.071 if tag == 'replace':
2025-07-02 04:52:33.071 atags += '^' * la
2025-07-02 04:52:33.071 btags += '^' * lb
2025-07-02 04:52:33.071 elif tag == 'delete':
2025-07-02 04:52:33.071 atags += '-' * la
2025-07-02 04:52:33.071 elif tag == 'insert':
2025-07-02 04:52:33.071 btags += '+' * lb
2025-07-02 04:52:33.071 elif tag == 'equal':
2025-07-02 04:52:33.072 atags += ' ' * la
2025-07-02 04:52:33.072 btags += ' ' * lb
2025-07-02 04:52:33.072 else:
2025-07-02 04:52:33.072 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.072 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.072 else:
2025-07-02 04:52:33.072 # the synch pair is identical
2025-07-02 04:52:33.072 yield ' ' + aelt
2025-07-02 04:52:33.072
2025-07-02 04:52:33.072 # pump out diffs from after the synch point
2025-07-02 04:52:33.072 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.072
2025-07-02 04:52:33.072 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.072 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.072
2025-07-02 04:52:33.072 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.072 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.072 alo = 340, ahi = 1101
2025-07-02 04:52:33.072 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.073 blo = 340, bhi = 1101
2025-07-02 04:52:33.073
2025-07-02 04:52:33.073 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.073 g = []
2025-07-02 04:52:33.073 if alo < ahi:
2025-07-02 04:52:33.073 if blo < bhi:
2025-07-02 04:52:33.073 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.073 else:
2025-07-02 04:52:33.073 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.073 elif blo < bhi:
2025-07-02 04:52:33.073 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.073
2025-07-02 04:52:33.073 > yield from g
2025-07-02 04:52:33.073
2025-07-02 04:52:33.073 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.073 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.073
2025-07-02 04:52:33.073 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.073 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.073 alo = 340, ahi = 1101
2025-07-02 04:52:33.073 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.074 blo = 340, bhi = 1101
2025-07-02 04:52:33.074
2025-07-02 04:52:33.074 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.074 r"""
2025-07-02 04:52:33.074 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.074 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.074 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.074 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.074
2025-07-02 04:52:33.074 Example:
2025-07-02 04:52:33.074
2025-07-02 04:52:33.074 >>> d = Differ()
2025-07-02 04:52:33.074 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.074 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.074 >>> print(''.join(results), end="")
2025-07-02 04:52:33.074 - abcDefghiJkl
2025-07-02 04:52:33.074 + abcdefGhijkl
2025-07-02 04:52:33.074 """
2025-07-02 04:52:33.075
2025-07-02 04:52:33.075 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.075 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.075 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.075 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.075 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.075
2025-07-02 04:52:33.075 # search for the pair that matches best without being identical
2025-07-02 04:52:33.075 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.075 # on junk -- unless we have to)
2025-07-02 04:52:33.075 for j in range(blo, bhi):
2025-07-02 04:52:33.075 bj = b[j]
2025-07-02 04:52:33.075 cruncher.set_seq2(bj)
2025-07-02 04:52:33.075 for i in range(alo, ahi):
2025-07-02 04:52:33.075 ai = a[i]
2025-07-02 04:52:33.075 if ai == bj:
2025-07-02 04:52:33.075 if eqi is None:
2025-07-02 04:52:33.075 eqi, eqj = i, j
2025-07-02 04:52:33.075 continue
2025-07-02 04:52:33.075 cruncher.set_seq1(ai)
2025-07-02 04:52:33.075 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.075 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.076 # compares by a factor of 3.
2025-07-02 04:52:33.076 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.076 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.076 # of the computation is cached by cruncher
2025-07-02 04:52:33.076 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.076 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.076 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.076 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.076 if best_ratio < cutoff:
2025-07-02 04:52:33.076 # no non-identical "pretty close" pair
2025-07-02 04:52:33.076 if eqi is None:
2025-07-02 04:52:33.076 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.076 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.076 return
2025-07-02 04:52:33.076 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.076 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.076 else:
2025-07-02 04:52:33.076 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.076 eqi = None
2025-07-02 04:52:33.077
2025-07-02 04:52:33.077 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.077 # identical
2025-07-02 04:52:33.077
2025-07-02 04:52:33.077 # pump out diffs from before the synch point
2025-07-02 04:52:33.077 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.077
2025-07-02 04:52:33.077 # do intraline marking on the synch pair
2025-07-02 04:52:33.077 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.077 if eqi is None:
2025-07-02 04:52:33.077 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.077 atags = btags = ""
2025-07-02 04:52:33.077 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.077 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.077 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.077 if tag == 'replace':
2025-07-02 04:52:33.077 atags += '^' * la
2025-07-02 04:52:33.077 btags += '^' * lb
2025-07-02 04:52:33.077 elif tag == 'delete':
2025-07-02 04:52:33.077 atags += '-' * la
2025-07-02 04:52:33.077 elif tag == 'insert':
2025-07-02 04:52:33.078 btags += '+' * lb
2025-07-02 04:52:33.078 elif tag == 'equal':
2025-07-02 04:52:33.078 atags += ' ' * la
2025-07-02 04:52:33.078 btags += ' ' * lb
2025-07-02 04:52:33.078 else:
2025-07-02 04:52:33.078 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.078 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.078 else:
2025-07-02 04:52:33.078 # the synch pair is identical
2025-07-02 04:52:33.078 yield ' ' + aelt
2025-07-02 04:52:33.078
2025-07-02 04:52:33.078 # pump out diffs from after the synch point
2025-07-02 04:52:33.078 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.078
2025-07-02 04:52:33.078 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.078 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.078
2025-07-02 04:52:33.078 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.078 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.078 alo = 341, ahi = 1101
2025-07-02 04:52:33.078 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.079 blo = 341, bhi = 1101
2025-07-02 04:52:33.079
2025-07-02 04:52:33.079 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.079 g = []
2025-07-02 04:52:33.079 if alo < ahi:
2025-07-02 04:52:33.079 if blo < bhi:
2025-07-02 04:52:33.079 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.079 else:
2025-07-02 04:52:33.079 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.079 elif blo < bhi:
2025-07-02 04:52:33.079 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.079
2025-07-02 04:52:33.079 > yield from g
2025-07-02 04:52:33.079
2025-07-02 04:52:33.079 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.079 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.079
2025-07-02 04:52:33.079 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.079 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.079 alo = 341, ahi = 1101
2025-07-02 04:52:33.079 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.080 blo = 341, bhi = 1101
2025-07-02 04:52:33.080
2025-07-02 04:52:33.080 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.080 r"""
2025-07-02 04:52:33.080 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.080 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.080 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.080 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.080
2025-07-02 04:52:33.080 Example:
2025-07-02 04:52:33.080
2025-07-02 04:52:33.080 >>> d = Differ()
2025-07-02 04:52:33.080 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.080 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.080 >>> print(''.join(results), end="")
2025-07-02 04:52:33.080 - abcDefghiJkl
2025-07-02 04:52:33.080 + abcdefGhijkl
2025-07-02 04:52:33.080 """
2025-07-02 04:52:33.080
2025-07-02 04:52:33.080 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.081 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.081 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.081 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.081 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.081
2025-07-02 04:52:33.081 # search for the pair that matches best without being identical
2025-07-02 04:52:33.081 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.081 # on junk -- unless we have to)
2025-07-02 04:52:33.081 for j in range(blo, bhi):
2025-07-02 04:52:33.081 bj = b[j]
2025-07-02 04:52:33.081 cruncher.set_seq2(bj)
2025-07-02 04:52:33.081 for i in range(alo, ahi):
2025-07-02 04:52:33.081 ai = a[i]
2025-07-02 04:52:33.081 if ai == bj:
2025-07-02 04:52:33.081 if eqi is None:
2025-07-02 04:52:33.081 eqi, eqj = i, j
2025-07-02 04:52:33.081 continue
2025-07-02 04:52:33.081 cruncher.set_seq1(ai)
2025-07-02 04:52:33.081 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.081 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.082 # compares by a factor of 3.
2025-07-02 04:52:33.082 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.082 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.082 # of the computation is cached by cruncher
2025-07-02 04:52:33.082 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.082 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.082 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.082 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.082 if best_ratio < cutoff:
2025-07-02 04:52:33.082 # no non-identical "pretty close" pair
2025-07-02 04:52:33.082 if eqi is None:
2025-07-02 04:52:33.082 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.082 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.082 return
2025-07-02 04:52:33.082 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.082 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.082 else:
2025-07-02 04:52:33.082 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.082 eqi = None
2025-07-02 04:52:33.082
2025-07-02 04:52:33.083 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.083 # identical
2025-07-02 04:52:33.083
2025-07-02 04:52:33.083 # pump out diffs from before the synch point
2025-07-02 04:52:33.083 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.083
2025-07-02 04:52:33.083 # do intraline marking on the synch pair
2025-07-02 04:52:33.083 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.083 if eqi is None:
2025-07-02 04:52:33.083 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.083 atags = btags = ""
2025-07-02 04:52:33.083 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.083 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.083 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.083 if tag == 'replace':
2025-07-02 04:52:33.083 atags += '^' * la
2025-07-02 04:52:33.083 btags += '^' * lb
2025-07-02 04:52:33.083 elif tag == 'delete':
2025-07-02 04:52:33.083 atags += '-' * la
2025-07-02 04:52:33.083 elif tag == 'insert':
2025-07-02 04:52:33.083 btags += '+' * lb
2025-07-02 04:52:33.084 elif tag == 'equal':
2025-07-02 04:52:33.084 atags += ' ' * la
2025-07-02 04:52:33.084 btags += ' ' * lb
2025-07-02 04:52:33.084 else:
2025-07-02 04:52:33.084 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.084 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.084 else:
2025-07-02 04:52:33.084 # the synch pair is identical
2025-07-02 04:52:33.084 yield ' ' + aelt
2025-07-02 04:52:33.084
2025-07-02 04:52:33.084 # pump out diffs from after the synch point
2025-07-02 04:52:33.084 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.084
2025-07-02 04:52:33.084 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.084 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.084
2025-07-02 04:52:33.084 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.084 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.084 alo = 342, ahi = 1101
2025-07-02 04:52:33.084 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.084 blo = 342, bhi = 1101
2025-07-02 04:52:33.085
2025-07-02 04:52:33.085 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.085 g = []
2025-07-02 04:52:33.085 if alo < ahi:
2025-07-02 04:52:33.085 if blo < bhi:
2025-07-02 04:52:33.085 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.085 else:
2025-07-02 04:52:33.085 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.085 elif blo < bhi:
2025-07-02 04:52:33.085 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.085
2025-07-02 04:52:33.085 > yield from g
2025-07-02 04:52:33.085
2025-07-02 04:52:33.085 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.085 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.085
2025-07-02 04:52:33.085 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.085 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.085 alo = 342, ahi = 1101
2025-07-02 04:52:33.085 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.085 blo = 342, bhi = 1101
2025-07-02 04:52:33.085
2025-07-02 04:52:33.086 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.086 r"""
2025-07-02 04:52:33.086 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.086 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.086 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.086 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.086
2025-07-02 04:52:33.086 Example:
2025-07-02 04:52:33.086
2025-07-02 04:52:33.086 >>> d = Differ()
2025-07-02 04:52:33.086 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.086 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.086 >>> print(''.join(results), end="")
2025-07-02 04:52:33.086 - abcDefghiJkl
2025-07-02 04:52:33.086 + abcdefGhijkl
2025-07-02 04:52:33.086 """
2025-07-02 04:52:33.086
2025-07-02 04:52:33.086 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.086 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.087 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.087 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.087 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.087
2025-07-02 04:52:33.087 # search for the pair that matches best without being identical
2025-07-02 04:52:33.087 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.087 # on junk -- unless we have to)
2025-07-02 04:52:33.087 for j in range(blo, bhi):
2025-07-02 04:52:33.087 bj = b[j]
2025-07-02 04:52:33.087 cruncher.set_seq2(bj)
2025-07-02 04:52:33.087 for i in range(alo, ahi):
2025-07-02 04:52:33.087 ai = a[i]
2025-07-02 04:52:33.087 if ai == bj:
2025-07-02 04:52:33.087 if eqi is None:
2025-07-02 04:52:33.087 eqi, eqj = i, j
2025-07-02 04:52:33.087 continue
2025-07-02 04:52:33.087 cruncher.set_seq1(ai)
2025-07-02 04:52:33.087 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.087 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.087 # compares by a factor of 3.
2025-07-02 04:52:33.087 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.087 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.088 # of the computation is cached by cruncher
2025-07-02 04:52:33.088 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.088 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.088 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.088 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.088 if best_ratio < cutoff:
2025-07-02 04:52:33.088 # no non-identical "pretty close" pair
2025-07-02 04:52:33.088 if eqi is None:
2025-07-02 04:52:33.088 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.088 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.088 return
2025-07-02 04:52:33.088 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.088 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.088 else:
2025-07-02 04:52:33.088 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.088 eqi = None
2025-07-02 04:52:33.088
2025-07-02 04:52:33.088 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.088 # identical
2025-07-02 04:52:33.088
2025-07-02 04:52:33.088 # pump out diffs from before the synch point
2025-07-02 04:52:33.089 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.089
2025-07-02 04:52:33.089 # do intraline marking on the synch pair
2025-07-02 04:52:33.089 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.089 if eqi is None:
2025-07-02 04:52:33.089 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.089 atags = btags = ""
2025-07-02 04:52:33.089 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.089 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.089 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.089 if tag == 'replace':
2025-07-02 04:52:33.089 atags += '^' * la
2025-07-02 04:52:33.089 btags += '^' * lb
2025-07-02 04:52:33.089 elif tag == 'delete':
2025-07-02 04:52:33.089 atags += '-' * la
2025-07-02 04:52:33.089 elif tag == 'insert':
2025-07-02 04:52:33.089 btags += '+' * lb
2025-07-02 04:52:33.089 elif tag == 'equal':
2025-07-02 04:52:33.089 atags += ' ' * la
2025-07-02 04:52:33.090 btags += ' ' * lb
2025-07-02 04:52:33.090 else:
2025-07-02 04:52:33.090 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.090 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.090 else:
2025-07-02 04:52:33.090 # the synch pair is identical
2025-07-02 04:52:33.090 yield ' ' + aelt
2025-07-02 04:52:33.090
2025-07-02 04:52:33.090 # pump out diffs from after the synch point
2025-07-02 04:52:33.090 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.090
2025-07-02 04:52:33.090 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.090 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.090
2025-07-02 04:52:33.090 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.090 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.090 alo = 343, ahi = 1101
2025-07-02 04:52:33.090 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.090 blo = 343, bhi = 1101
2025-07-02 04:52:33.090
2025-07-02 04:52:33.090 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.091 g = []
2025-07-02 04:52:33.091 if alo < ahi:
2025-07-02 04:52:33.091 if blo < bhi:
2025-07-02 04:52:33.091 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.091 else:
2025-07-02 04:52:33.091 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.091 elif blo < bhi:
2025-07-02 04:52:33.091 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.091
2025-07-02 04:52:33.091 > yield from g
2025-07-02 04:52:33.091
2025-07-02 04:52:33.091 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.091 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.091
2025-07-02 04:52:33.091 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.091 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.091 alo = 343, ahi = 1101
2025-07-02 04:52:33.091 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.091 blo = 343, bhi = 1101
2025-07-02 04:52:33.091
2025-07-02 04:52:33.092 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.092 r"""
2025-07-02 04:52:33.092 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.092 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.092 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.092 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.092
2025-07-02 04:52:33.092 Example:
2025-07-02 04:52:33.092
2025-07-02 04:52:33.092 >>> d = Differ()
2025-07-02 04:52:33.092 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.092 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.092 >>> print(''.join(results), end="")
2025-07-02 04:52:33.092 - abcDefghiJkl
2025-07-02 04:52:33.092 + abcdefGhijkl
2025-07-02 04:52:33.092 """
2025-07-02 04:52:33.092
2025-07-02 04:52:33.092 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.092 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.092 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.093 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.093 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.093
2025-07-02 04:52:33.093 # search for the pair that matches best without being identical
2025-07-02 04:52:33.093 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.093 # on junk -- unless we have to)
2025-07-02 04:52:33.093 for j in range(blo, bhi):
2025-07-02 04:52:33.093 bj = b[j]
2025-07-02 04:52:33.093 cruncher.set_seq2(bj)
2025-07-02 04:52:33.093 for i in range(alo, ahi):
2025-07-02 04:52:33.093 ai = a[i]
2025-07-02 04:52:33.093 if ai == bj:
2025-07-02 04:52:33.093 if eqi is None:
2025-07-02 04:52:33.093 eqi, eqj = i, j
2025-07-02 04:52:33.093 continue
2025-07-02 04:52:33.093 cruncher.set_seq1(ai)
2025-07-02 04:52:33.093 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.093 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.093 # compares by a factor of 3.
2025-07-02 04:52:33.093 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.093 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.093 # of the computation is cached by cruncher
2025-07-02 04:52:33.094 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.094 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.094 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.094 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.094 if best_ratio < cutoff:
2025-07-02 04:52:33.094 # no non-identical "pretty close" pair
2025-07-02 04:52:33.094 if eqi is None:
2025-07-02 04:52:33.094 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.094 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.094 return
2025-07-02 04:52:33.094 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.094 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.094 else:
2025-07-02 04:52:33.094 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.094 eqi = None
2025-07-02 04:52:33.094
2025-07-02 04:52:33.094 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.094 # identical
2025-07-02 04:52:33.094
2025-07-02 04:52:33.094 # pump out diffs from before the synch point
2025-07-02 04:52:33.094 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.095
2025-07-02 04:52:33.095 # do intraline marking on the synch pair
2025-07-02 04:52:33.095 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.095 if eqi is None:
2025-07-02 04:52:33.095 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.095 atags = btags = ""
2025-07-02 04:52:33.095 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.095 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.095 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.095 if tag == 'replace':
2025-07-02 04:52:33.095 atags += '^' * la
2025-07-02 04:52:33.095 btags += '^' * lb
2025-07-02 04:52:33.095 elif tag == 'delete':
2025-07-02 04:52:33.095 atags += '-' * la
2025-07-02 04:52:33.095 elif tag == 'insert':
2025-07-02 04:52:33.095 btags += '+' * lb
2025-07-02 04:52:33.095 elif tag == 'equal':
2025-07-02 04:52:33.095 atags += ' ' * la
2025-07-02 04:52:33.095 btags += ' ' * lb
2025-07-02 04:52:33.095 else:
2025-07-02 04:52:33.095 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.096 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.096 else:
2025-07-02 04:52:33.096 # the synch pair is identical
2025-07-02 04:52:33.096 yield ' ' + aelt
2025-07-02 04:52:33.096
2025-07-02 04:52:33.096 # pump out diffs from after the synch point
2025-07-02 04:52:33.096 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.096
2025-07-02 04:52:33.096 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.096 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.096
2025-07-02 04:52:33.096 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.096 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.096 alo = 344, ahi = 1101
2025-07-02 04:52:33.096 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.096 blo = 344, bhi = 1101
2025-07-02 04:52:33.096
2025-07-02 04:52:33.096 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.096 g = []
2025-07-02 04:52:33.096 if alo < ahi:
2025-07-02 04:52:33.096 if blo < bhi:
2025-07-02 04:52:33.096 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.097 else:
2025-07-02 04:52:33.097 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.097 elif blo < bhi:
2025-07-02 04:52:33.097 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.097
2025-07-02 04:52:33.097 > yield from g
2025-07-02 04:52:33.097
2025-07-02 04:52:33.097 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.097 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.097
2025-07-02 04:52:33.097 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.097 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.097 alo = 344, ahi = 1101
2025-07-02 04:52:33.097 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.097 blo = 344, bhi = 1101
2025-07-02 04:52:33.097
2025-07-02 04:52:33.097 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.097 r"""
2025-07-02 04:52:33.097 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.098 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.098 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.098 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.098
2025-07-02 04:52:33.098 Example:
2025-07-02 04:52:33.098
2025-07-02 04:52:33.098 >>> d = Differ()
2025-07-02 04:52:33.098 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.098 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.098 >>> print(''.join(results), end="")
2025-07-02 04:52:33.098 - abcDefghiJkl
2025-07-02 04:52:33.098 + abcdefGhijkl
2025-07-02 04:52:33.098 """
2025-07-02 04:52:33.098
2025-07-02 04:52:33.098 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.098 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.098 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.099 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.099 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.099
2025-07-02 04:52:33.099 # search for the pair that matches best without being identical
2025-07-02 04:52:33.099 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.099 # on junk -- unless we have to)
2025-07-02 04:52:33.099 for j in range(blo, bhi):
2025-07-02 04:52:33.099 bj = b[j]
2025-07-02 04:52:33.099 cruncher.set_seq2(bj)
2025-07-02 04:52:33.099 for i in range(alo, ahi):
2025-07-02 04:52:33.099 ai = a[i]
2025-07-02 04:52:33.099 if ai == bj:
2025-07-02 04:52:33.099 if eqi is None:
2025-07-02 04:52:33.099 eqi, eqj = i, j
2025-07-02 04:52:33.099 continue
2025-07-02 04:52:33.099 cruncher.set_seq1(ai)
2025-07-02 04:52:33.099 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.099 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.099 # compares by a factor of 3.
2025-07-02 04:52:33.099 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.099 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.100 # of the computation is cached by cruncher
2025-07-02 04:52:33.100 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.100 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.100 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.100 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.100 if best_ratio < cutoff:
2025-07-02 04:52:33.100 # no non-identical "pretty close" pair
2025-07-02 04:52:33.100 if eqi is None:
2025-07-02 04:52:33.100 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.100 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.100 return
2025-07-02 04:52:33.100 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.100 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.100 else:
2025-07-02 04:52:33.100 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.100 eqi = None
2025-07-02 04:52:33.100
2025-07-02 04:52:33.100 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.100 # identical
2025-07-02 04:52:33.100
2025-07-02 04:52:33.100 # pump out diffs from before the synch point
2025-07-02 04:52:33.100 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.101
2025-07-02 04:52:33.101 # do intraline marking on the synch pair
2025-07-02 04:52:33.101 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.101 if eqi is None:
2025-07-02 04:52:33.101 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.101 atags = btags = ""
2025-07-02 04:52:33.101 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.101 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.101 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.101 if tag == 'replace':
2025-07-02 04:52:33.101 atags += '^' * la
2025-07-02 04:52:33.101 btags += '^' * lb
2025-07-02 04:52:33.101 elif tag == 'delete':
2025-07-02 04:52:33.101 atags += '-' * la
2025-07-02 04:52:33.101 elif tag == 'insert':
2025-07-02 04:52:33.101 btags += '+' * lb
2025-07-02 04:52:33.101 elif tag == 'equal':
2025-07-02 04:52:33.101 atags += ' ' * la
2025-07-02 04:52:33.101 btags += ' ' * lb
2025-07-02 04:52:33.101 else:
2025-07-02 04:52:33.101 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.102 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.102 else:
2025-07-02 04:52:33.102 # the synch pair is identical
2025-07-02 04:52:33.102 yield ' ' + aelt
2025-07-02 04:52:33.102
2025-07-02 04:52:33.102 # pump out diffs from after the synch point
2025-07-02 04:52:33.102 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.102
2025-07-02 04:52:33.102 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.102 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.102
2025-07-02 04:52:33.102 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.102 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.102 alo = 345, ahi = 1101
2025-07-02 04:52:33.102 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.102 blo = 345, bhi = 1101
2025-07-02 04:52:33.102
2025-07-02 04:52:33.102 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.102 g = []
2025-07-02 04:52:33.102 if alo < ahi:
2025-07-02 04:52:33.102 if blo < bhi:
2025-07-02 04:52:33.102 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.103 else:
2025-07-02 04:52:33.103 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.103 elif blo < bhi:
2025-07-02 04:52:33.103 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.103
2025-07-02 04:52:33.103 > yield from g
2025-07-02 04:52:33.103
2025-07-02 04:52:33.103 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.103 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.103
2025-07-02 04:52:33.103 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.103 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.103 alo = 345, ahi = 1101
2025-07-02 04:52:33.103 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.103 blo = 345, bhi = 1101
2025-07-02 04:52:33.103
2025-07-02 04:52:33.103 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.103 r"""
2025-07-02 04:52:33.103 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.103 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.103 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.104 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.104
2025-07-02 04:52:33.104 Example:
2025-07-02 04:52:33.104
2025-07-02 04:52:33.104 >>> d = Differ()
2025-07-02 04:52:33.104 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.104 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.104 >>> print(''.join(results), end="")
2025-07-02 04:52:33.104 - abcDefghiJkl
2025-07-02 04:52:33.104 + abcdefGhijkl
2025-07-02 04:52:33.104 """
2025-07-02 04:52:33.104
2025-07-02 04:52:33.104 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.104 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.104 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.104 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.104 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.104
2025-07-02 04:52:33.104 # search for the pair that matches best without being identical
2025-07-02 04:52:33.104 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.105 # on junk -- unless we have to)
2025-07-02 04:52:33.105 for j in range(blo, bhi):
2025-07-02 04:52:33.105 bj = b[j]
2025-07-02 04:52:33.105 cruncher.set_seq2(bj)
2025-07-02 04:52:33.105 for i in range(alo, ahi):
2025-07-02 04:52:33.105 ai = a[i]
2025-07-02 04:52:33.105 if ai == bj:
2025-07-02 04:52:33.105 if eqi is None:
2025-07-02 04:52:33.105 eqi, eqj = i, j
2025-07-02 04:52:33.105 continue
2025-07-02 04:52:33.105 cruncher.set_seq1(ai)
2025-07-02 04:52:33.105 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.105 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.105 # compares by a factor of 3.
2025-07-02 04:52:33.105 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.105 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.105 # of the computation is cached by cruncher
2025-07-02 04:52:33.105 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.105 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.106 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.106 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.106 if best_ratio < cutoff:
2025-07-02 04:52:33.106 # no non-identical "pretty close" pair
2025-07-02 04:52:33.106 if eqi is None:
2025-07-02 04:52:33.106 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.106 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.106 return
2025-07-02 04:52:33.106 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.106 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.106 else:
2025-07-02 04:52:33.106 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.106 eqi = None
2025-07-02 04:52:33.106
2025-07-02 04:52:33.106 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.106 # identical
2025-07-02 04:52:33.106
2025-07-02 04:52:33.106 # pump out diffs from before the synch point
2025-07-02 04:52:33.106 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.106
2025-07-02 04:52:33.106 # do intraline marking on the synch pair
2025-07-02 04:52:33.107 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.107 if eqi is None:
2025-07-02 04:52:33.107 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.107 atags = btags = ""
2025-07-02 04:52:33.107 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.107 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.107 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.107 if tag == 'replace':
2025-07-02 04:52:33.107 atags += '^' * la
2025-07-02 04:52:33.107 btags += '^' * lb
2025-07-02 04:52:33.107 elif tag == 'delete':
2025-07-02 04:52:33.107 atags += '-' * la
2025-07-02 04:52:33.107 elif tag == 'insert':
2025-07-02 04:52:33.107 btags += '+' * lb
2025-07-02 04:52:33.107 elif tag == 'equal':
2025-07-02 04:52:33.107 atags += ' ' * la
2025-07-02 04:52:33.107 btags += ' ' * lb
2025-07-02 04:52:33.107 else:
2025-07-02 04:52:33.107 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.107 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.107 else:
2025-07-02 04:52:33.108 # the synch pair is identical
2025-07-02 04:52:33.108 yield ' ' + aelt
2025-07-02 04:52:33.108
2025-07-02 04:52:33.108 # pump out diffs from after the synch point
2025-07-02 04:52:33.108 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.108
2025-07-02 04:52:33.108 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.108 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.108
2025-07-02 04:52:33.108 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.108 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.108 alo = 346, ahi = 1101
2025-07-02 04:52:33.108 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.108 blo = 346, bhi = 1101
2025-07-02 04:52:33.108
2025-07-02 04:52:33.108 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.108 g = []
2025-07-02 04:52:33.108 if alo < ahi:
2025-07-02 04:52:33.108 if blo < bhi:
2025-07-02 04:52:33.108 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.108 else:
2025-07-02 04:52:33.109 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.109 elif blo < bhi:
2025-07-02 04:52:33.109 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.109
2025-07-02 04:52:33.109 > yield from g
2025-07-02 04:52:33.109
2025-07-02 04:52:33.109 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.109 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.109
2025-07-02 04:52:33.109 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.109 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.109 alo = 346, ahi = 1101
2025-07-02 04:52:33.109 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.109 blo = 346, bhi = 1101
2025-07-02 04:52:33.109
2025-07-02 04:52:33.109 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.109 r"""
2025-07-02 04:52:33.109 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.109 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.109 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.109 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.110
2025-07-02 04:52:33.110 Example:
2025-07-02 04:52:33.110
2025-07-02 04:52:33.110 >>> d = Differ()
2025-07-02 04:52:33.110 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.110 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.110 >>> print(''.join(results), end="")
2025-07-02 04:52:33.110 - abcDefghiJkl
2025-07-02 04:52:33.110 + abcdefGhijkl
2025-07-02 04:52:33.110 """
2025-07-02 04:52:33.110
2025-07-02 04:52:33.110 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.110 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.110 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.110 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.110 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.110
2025-07-02 04:52:33.110 # search for the pair that matches best without being identical
2025-07-02 04:52:33.110 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.110 # on junk -- unless we have to)
2025-07-02 04:52:33.111 for j in range(blo, bhi):
2025-07-02 04:52:33.111 bj = b[j]
2025-07-02 04:52:33.111 cruncher.set_seq2(bj)
2025-07-02 04:52:33.111 for i in range(alo, ahi):
2025-07-02 04:52:33.111 ai = a[i]
2025-07-02 04:52:33.111 if ai == bj:
2025-07-02 04:52:33.111 if eqi is None:
2025-07-02 04:52:33.111 eqi, eqj = i, j
2025-07-02 04:52:33.111 continue
2025-07-02 04:52:33.111 cruncher.set_seq1(ai)
2025-07-02 04:52:33.111 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.111 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.111 # compares by a factor of 3.
2025-07-02 04:52:33.111 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.111 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.111 # of the computation is cached by cruncher
2025-07-02 04:52:33.111 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.111 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.111 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.111 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.111 if best_ratio < cutoff:
2025-07-02 04:52:33.111 # no non-identical "pretty close" pair
2025-07-02 04:52:33.112 if eqi is None:
2025-07-02 04:52:33.112 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.112 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.112 return
2025-07-02 04:52:33.112 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.112 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.112 else:
2025-07-02 04:52:33.112 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.112 eqi = None
2025-07-02 04:52:33.112
2025-07-02 04:52:33.112 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.112 # identical
2025-07-02 04:52:33.112
2025-07-02 04:52:33.112 # pump out diffs from before the synch point
2025-07-02 04:52:33.112 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.112
2025-07-02 04:52:33.112 # do intraline marking on the synch pair
2025-07-02 04:52:33.112 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.112 if eqi is None:
2025-07-02 04:52:33.112 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.112 atags = btags = ""
2025-07-02 04:52:33.113 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.113 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.113 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.113 if tag == 'replace':
2025-07-02 04:52:33.113 atags += '^' * la
2025-07-02 04:52:33.113 btags += '^' * lb
2025-07-02 04:52:33.113 elif tag == 'delete':
2025-07-02 04:52:33.113 atags += '-' * la
2025-07-02 04:52:33.113 elif tag == 'insert':
2025-07-02 04:52:33.113 btags += '+' * lb
2025-07-02 04:52:33.113 elif tag == 'equal':
2025-07-02 04:52:33.113 atags += ' ' * la
2025-07-02 04:52:33.113 btags += ' ' * lb
2025-07-02 04:52:33.113 else:
2025-07-02 04:52:33.113 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.113 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.113 else:
2025-07-02 04:52:33.113 # the synch pair is identical
2025-07-02 04:52:33.113 yield ' ' + aelt
2025-07-02 04:52:33.113
2025-07-02 04:52:33.113 # pump out diffs from after the synch point
2025-07-02 04:52:33.114 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.114
2025-07-02 04:52:33.114 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.114 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.114
2025-07-02 04:52:33.114 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.114 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.114 alo = 347, ahi = 1101
2025-07-02 04:52:33.114 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.114 blo = 347, bhi = 1101
2025-07-02 04:52:33.114
2025-07-02 04:52:33.114 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.114 g = []
2025-07-02 04:52:33.114 if alo < ahi:
2025-07-02 04:52:33.114 if blo < bhi:
2025-07-02 04:52:33.114 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.114 else:
2025-07-02 04:52:33.114 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.114 elif blo < bhi:
2025-07-02 04:52:33.115 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.115
2025-07-02 04:52:33.115 > yield from g
2025-07-02 04:52:33.115
2025-07-02 04:52:33.115 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.115 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.115
2025-07-02 04:52:33.115 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.115 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.115 alo = 347, ahi = 1101
2025-07-02 04:52:33.115 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.115 blo = 347, bhi = 1101
2025-07-02 04:52:33.115
2025-07-02 04:52:33.115 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.115 r"""
2025-07-02 04:52:33.115 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.115 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.115 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.115 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.116
2025-07-02 04:52:33.116 Example:
2025-07-02 04:52:33.116
2025-07-02 04:52:33.116 >>> d = Differ()
2025-07-02 04:52:33.116 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.116 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.116 >>> print(''.join(results), end="")
2025-07-02 04:52:33.116 - abcDefghiJkl
2025-07-02 04:52:33.116 + abcdefGhijkl
2025-07-02 04:52:33.116 """
2025-07-02 04:52:33.116
2025-07-02 04:52:33.116 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.116 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.116 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.116 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.116 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.116
2025-07-02 04:52:33.116 # search for the pair that matches best without being identical
2025-07-02 04:52:33.116 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.117 # on junk -- unless we have to)
2025-07-02 04:52:33.117 for j in range(blo, bhi):
2025-07-02 04:52:33.117 bj = b[j]
2025-07-02 04:52:33.117 cruncher.set_seq2(bj)
2025-07-02 04:52:33.117 for i in range(alo, ahi):
2025-07-02 04:52:33.117 ai = a[i]
2025-07-02 04:52:33.117 if ai == bj:
2025-07-02 04:52:33.117 if eqi is None:
2025-07-02 04:52:33.117 eqi, eqj = i, j
2025-07-02 04:52:33.117 continue
2025-07-02 04:52:33.117 cruncher.set_seq1(ai)
2025-07-02 04:52:33.117 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.117 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.117 # compares by a factor of 3.
2025-07-02 04:52:33.117 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.117 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.117 # of the computation is cached by cruncher
2025-07-02 04:52:33.117 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.117 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.117 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.117 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.118 if best_ratio < cutoff:
2025-07-02 04:52:33.118 # no non-identical "pretty close" pair
2025-07-02 04:52:33.118 if eqi is None:
2025-07-02 04:52:33.118 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.118 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.118 return
2025-07-02 04:52:33.118 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.118 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.118 else:
2025-07-02 04:52:33.118 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.118 eqi = None
2025-07-02 04:52:33.118
2025-07-02 04:52:33.118 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.118 # identical
2025-07-02 04:52:33.118
2025-07-02 04:52:33.118 # pump out diffs from before the synch point
2025-07-02 04:52:33.118 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.118
2025-07-02 04:52:33.118 # do intraline marking on the synch pair
2025-07-02 04:52:33.118 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.118 if eqi is None:
2025-07-02 04:52:33.119 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.119 atags = btags = ""
2025-07-02 04:52:33.119 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.119 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.119 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.119 if tag == 'replace':
2025-07-02 04:52:33.119 atags += '^' * la
2025-07-02 04:52:33.119 btags += '^' * lb
2025-07-02 04:52:33.119 elif tag == 'delete':
2025-07-02 04:52:33.119 atags += '-' * la
2025-07-02 04:52:33.119 elif tag == 'insert':
2025-07-02 04:52:33.119 btags += '+' * lb
2025-07-02 04:52:33.119 elif tag == 'equal':
2025-07-02 04:52:33.119 atags += ' ' * la
2025-07-02 04:52:33.119 btags += ' ' * lb
2025-07-02 04:52:33.119 else:
2025-07-02 04:52:33.119 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.119 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.119 else:
2025-07-02 04:52:33.119 # the synch pair is identical
2025-07-02 04:52:33.119 yield ' ' + aelt
2025-07-02 04:52:33.119
2025-07-02 04:52:33.120 # pump out diffs from after the synch point
2025-07-02 04:52:33.120 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.120
2025-07-02 04:52:33.120 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.120 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.120
2025-07-02 04:52:33.120 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.120 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.120 alo = 348, ahi = 1101
2025-07-02 04:52:33.120 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.120 blo = 348, bhi = 1101
2025-07-02 04:52:33.120
2025-07-02 04:52:33.120 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.120 g = []
2025-07-02 04:52:33.120 if alo < ahi:
2025-07-02 04:52:33.120 if blo < bhi:
2025-07-02 04:52:33.120 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.120 else:
2025-07-02 04:52:33.120 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.120 elif blo < bhi:
2025-07-02 04:52:33.120 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.121
2025-07-02 04:52:33.121 > yield from g
2025-07-02 04:52:33.121
2025-07-02 04:52:33.121 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.121 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.121
2025-07-02 04:52:33.121 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.121 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.121 alo = 348, ahi = 1101
2025-07-02 04:52:33.121 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.121 blo = 348, bhi = 1101
2025-07-02 04:52:33.121
2025-07-02 04:52:33.121 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.121 r"""
2025-07-02 04:52:33.121 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.121 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.121 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.121 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.121
2025-07-02 04:52:33.121 Example:
2025-07-02 04:52:33.121
2025-07-02 04:52:33.122 >>> d = Differ()
2025-07-02 04:52:33.122 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.122 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.122 >>> print(''.join(results), end="")
2025-07-02 04:52:33.122 - abcDefghiJkl
2025-07-02 04:52:33.122 + abcdefGhijkl
2025-07-02 04:52:33.122 """
2025-07-02 04:52:33.122
2025-07-02 04:52:33.122 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.122 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.122 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.122 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.122 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.122
2025-07-02 04:52:33.122 # search for the pair that matches best without being identical
2025-07-02 04:52:33.122 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.122 # on junk -- unless we have to)
2025-07-02 04:52:33.123 for j in range(blo, bhi):
2025-07-02 04:52:33.123 bj = b[j]
2025-07-02 04:52:33.123 cruncher.set_seq2(bj)
2025-07-02 04:52:33.123 for i in range(alo, ahi):
2025-07-02 04:52:33.123 ai = a[i]
2025-07-02 04:52:33.123 if ai == bj:
2025-07-02 04:52:33.123 if eqi is None:
2025-07-02 04:52:33.123 eqi, eqj = i, j
2025-07-02 04:52:33.123 continue
2025-07-02 04:52:33.123 cruncher.set_seq1(ai)
2025-07-02 04:52:33.123 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.123 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.123 # compares by a factor of 3.
2025-07-02 04:52:33.123 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.123 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.123 # of the computation is cached by cruncher
2025-07-02 04:52:33.123 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.123 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.123 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.123 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.124 if best_ratio < cutoff:
2025-07-02 04:52:33.124 # no non-identical "pretty close" pair
2025-07-02 04:52:33.124 if eqi is None:
2025-07-02 04:52:33.124 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.124 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.124 return
2025-07-02 04:52:33.124 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.124 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.124 else:
2025-07-02 04:52:33.124 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.124 eqi = None
2025-07-02 04:52:33.124
2025-07-02 04:52:33.124 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.124 # identical
2025-07-02 04:52:33.124
2025-07-02 04:52:33.124 # pump out diffs from before the synch point
2025-07-02 04:52:33.124 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.124
2025-07-02 04:52:33.124 # do intraline marking on the synch pair
2025-07-02 04:52:33.124 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.124 if eqi is None:
2025-07-02 04:52:33.124 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.125 atags = btags = ""
2025-07-02 04:52:33.125 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.125 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.125 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.125 if tag == 'replace':
2025-07-02 04:52:33.125 atags += '^' * la
2025-07-02 04:52:33.125 btags += '^' * lb
2025-07-02 04:52:33.125 elif tag == 'delete':
2025-07-02 04:52:33.125 atags += '-' * la
2025-07-02 04:52:33.125 elif tag == 'insert':
2025-07-02 04:52:33.125 btags += '+' * lb
2025-07-02 04:52:33.125 elif tag == 'equal':
2025-07-02 04:52:33.125 atags += ' ' * la
2025-07-02 04:52:33.125 btags += ' ' * lb
2025-07-02 04:52:33.125 else:
2025-07-02 04:52:33.125 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.125 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.125 else:
2025-07-02 04:52:33.125 # the synch pair is identical
2025-07-02 04:52:33.125 yield ' ' + aelt
2025-07-02 04:52:33.125
2025-07-02 04:52:33.126 # pump out diffs from after the synch point
2025-07-02 04:52:33.126 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.126
2025-07-02 04:52:33.126 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.126 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.126
2025-07-02 04:52:33.126 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.126 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.126 alo = 349, ahi = 1101
2025-07-02 04:52:33.126 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.126 blo = 349, bhi = 1101
2025-07-02 04:52:33.126
2025-07-02 04:52:33.126 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.126 g = []
2025-07-02 04:52:33.126 if alo < ahi:
2025-07-02 04:52:33.126 if blo < bhi:
2025-07-02 04:52:33.126 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.126 else:
2025-07-02 04:52:33.126 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.126 elif blo < bhi:
2025-07-02 04:52:33.126 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.126
2025-07-02 04:52:33.127 > yield from g
2025-07-02 04:52:33.127
2025-07-02 04:52:33.127 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.127 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.127
2025-07-02 04:52:33.127 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.127 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.127 alo = 349, ahi = 1101
2025-07-02 04:52:33.127 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.127 blo = 349, bhi = 1101
2025-07-02 04:52:33.127
2025-07-02 04:52:33.127 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.127 r"""
2025-07-02 04:52:33.127 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.127 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.127 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.127 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.127
2025-07-02 04:52:33.127 Example:
2025-07-02 04:52:33.127
2025-07-02 04:52:33.127 >>> d = Differ()
2025-07-02 04:52:33.128 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.128 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.128 >>> print(''.join(results), end="")
2025-07-02 04:52:33.128 - abcDefghiJkl
2025-07-02 04:52:33.128 + abcdefGhijkl
2025-07-02 04:52:33.128 """
2025-07-02 04:52:33.128
2025-07-02 04:52:33.128 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.128 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.128 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.128 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.128 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.128
2025-07-02 04:52:33.128 # search for the pair that matches best without being identical
2025-07-02 04:52:33.128 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.128 # on junk -- unless we have to)
2025-07-02 04:52:33.128 for j in range(blo, bhi):
2025-07-02 04:52:33.129 bj = b[j]
2025-07-02 04:52:33.129 cruncher.set_seq2(bj)
2025-07-02 04:52:33.129 for i in range(alo, ahi):
2025-07-02 04:52:33.129 ai = a[i]
2025-07-02 04:52:33.129 if ai == bj:
2025-07-02 04:52:33.129 if eqi is None:
2025-07-02 04:52:33.129 eqi, eqj = i, j
2025-07-02 04:52:33.129 continue
2025-07-02 04:52:33.129 cruncher.set_seq1(ai)
2025-07-02 04:52:33.129 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.129 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.129 # compares by a factor of 3.
2025-07-02 04:52:33.129 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.129 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.129 # of the computation is cached by cruncher
2025-07-02 04:52:33.129 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.129 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.129 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.129 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.130 if best_ratio < cutoff:
2025-07-02 04:52:33.130 # no non-identical "pretty close" pair
2025-07-02 04:52:33.130 if eqi is None:
2025-07-02 04:52:33.130 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.130 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.130 return
2025-07-02 04:52:33.130 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.130 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.130 else:
2025-07-02 04:52:33.130 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.130 eqi = None
2025-07-02 04:52:33.130
2025-07-02 04:52:33.130 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.130 # identical
2025-07-02 04:52:33.130
2025-07-02 04:52:33.130 # pump out diffs from before the synch point
2025-07-02 04:52:33.130 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.130
2025-07-02 04:52:33.130 # do intraline marking on the synch pair
2025-07-02 04:52:33.131 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.131 if eqi is None:
2025-07-02 04:52:33.131 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.131 atags = btags = ""
2025-07-02 04:52:33.131 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.131 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.131 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.131 if tag == 'replace':
2025-07-02 04:52:33.131 atags += '^' * la
2025-07-02 04:52:33.131 btags += '^' * lb
2025-07-02 04:52:33.131 elif tag == 'delete':
2025-07-02 04:52:33.131 atags += '-' * la
2025-07-02 04:52:33.131 elif tag == 'insert':
2025-07-02 04:52:33.131 btags += '+' * lb
2025-07-02 04:52:33.131 elif tag == 'equal':
2025-07-02 04:52:33.131 atags += ' ' * la
2025-07-02 04:52:33.131 btags += ' ' * lb
2025-07-02 04:52:33.131 else:
2025-07-02 04:52:33.131 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.131 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.132 else:
2025-07-02 04:52:33.132 # the synch pair is identical
2025-07-02 04:52:33.132 yield ' ' + aelt
2025-07-02 04:52:33.132
2025-07-02 04:52:33.132 # pump out diffs from after the synch point
2025-07-02 04:52:33.132 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.132
2025-07-02 04:52:33.132 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.132 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.132
2025-07-02 04:52:33.132 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.132 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.132 alo = 350, ahi = 1101
2025-07-02 04:52:33.132 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.132 blo = 350, bhi = 1101
2025-07-02 04:52:33.132
2025-07-02 04:52:33.132 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.132 g = []
2025-07-02 04:52:33.132 if alo < ahi:
2025-07-02 04:52:33.132 if blo < bhi:
2025-07-02 04:52:33.132 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.133 else:
2025-07-02 04:52:33.133 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.133 elif blo < bhi:
2025-07-02 04:52:33.133 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.133
2025-07-02 04:52:33.133 > yield from g
2025-07-02 04:52:33.133
2025-07-02 04:52:33.133 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.133 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.133
2025-07-02 04:52:33.133 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.133 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.133 alo = 350, ahi = 1101
2025-07-02 04:52:33.133 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.133 blo = 350, bhi = 1101
2025-07-02 04:52:33.133
2025-07-02 04:52:33.133 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.133 r"""
2025-07-02 04:52:33.133 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.133 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.133 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.134 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.134
2025-07-02 04:52:33.134 Example:
2025-07-02 04:52:33.134
2025-07-02 04:52:33.134 >>> d = Differ()
2025-07-02 04:52:33.134 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.134 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.134 >>> print(''.join(results), end="")
2025-07-02 04:52:33.134 - abcDefghiJkl
2025-07-02 04:52:33.134 + abcdefGhijkl
2025-07-02 04:52:33.134 """
2025-07-02 04:52:33.134
2025-07-02 04:52:33.134 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.134 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.134 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.134 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.134 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.134
2025-07-02 04:52:33.134 # search for the pair that matches best without being identical
2025-07-02 04:52:33.135 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.135 # on junk -- unless we have to)
2025-07-02 04:52:33.135 for j in range(blo, bhi):
2025-07-02 04:52:33.135 bj = b[j]
2025-07-02 04:52:33.135 cruncher.set_seq2(bj)
2025-07-02 04:52:33.135 for i in range(alo, ahi):
2025-07-02 04:52:33.135 ai = a[i]
2025-07-02 04:52:33.135 if ai == bj:
2025-07-02 04:52:33.135 if eqi is None:
2025-07-02 04:52:33.135 eqi, eqj = i, j
2025-07-02 04:52:33.135 continue
2025-07-02 04:52:33.135 cruncher.set_seq1(ai)
2025-07-02 04:52:33.135 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.135 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.135 # compares by a factor of 3.
2025-07-02 04:52:33.135 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.135 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.135 # of the computation is cached by cruncher
2025-07-02 04:52:33.135 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.135 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.135 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.136 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.136 if best_ratio < cutoff:
2025-07-02 04:52:33.136 # no non-identical "pretty close" pair
2025-07-02 04:52:33.136 if eqi is None:
2025-07-02 04:52:33.136 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.136 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.136 return
2025-07-02 04:52:33.136 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.136 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.136 else:
2025-07-02 04:52:33.136 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.136 eqi = None
2025-07-02 04:52:33.136
2025-07-02 04:52:33.136 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.136 # identical
2025-07-02 04:52:33.136
2025-07-02 04:52:33.136 # pump out diffs from before the synch point
2025-07-02 04:52:33.136 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.136
2025-07-02 04:52:33.136 # do intraline marking on the synch pair
2025-07-02 04:52:33.136 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.136 if eqi is None:
2025-07-02 04:52:33.137 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.137 atags = btags = ""
2025-07-02 04:52:33.137 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.137 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.137 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.137 if tag == 'replace':
2025-07-02 04:52:33.137 atags += '^' * la
2025-07-02 04:52:33.137 btags += '^' * lb
2025-07-02 04:52:33.137 elif tag == 'delete':
2025-07-02 04:52:33.137 atags += '-' * la
2025-07-02 04:52:33.137 elif tag == 'insert':
2025-07-02 04:52:33.137 btags += '+' * lb
2025-07-02 04:52:33.137 elif tag == 'equal':
2025-07-02 04:52:33.137 atags += ' ' * la
2025-07-02 04:52:33.137 btags += ' ' * lb
2025-07-02 04:52:33.137 else:
2025-07-02 04:52:33.137 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.137 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.137 else:
2025-07-02 04:52:33.137 # the synch pair is identical
2025-07-02 04:52:33.137 yield ' ' + aelt
2025-07-02 04:52:33.138
2025-07-02 04:52:33.138 # pump out diffs from after the synch point
2025-07-02 04:52:33.138 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.138
2025-07-02 04:52:33.138 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.138 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.138
2025-07-02 04:52:33.138 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.138 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.138 alo = 351, ahi = 1101
2025-07-02 04:52:33.138 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.138 blo = 351, bhi = 1101
2025-07-02 04:52:33.138
2025-07-02 04:52:33.138 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.138 g = []
2025-07-02 04:52:33.138 if alo < ahi:
2025-07-02 04:52:33.138 if blo < bhi:
2025-07-02 04:52:33.138 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.138 else:
2025-07-02 04:52:33.139 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.139 elif blo < bhi:
2025-07-02 04:52:33.139 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.139
2025-07-02 04:52:33.139 > yield from g
2025-07-02 04:52:33.139
2025-07-02 04:52:33.139 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.139 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.139
2025-07-02 04:52:33.139 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.139 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.139 alo = 351, ahi = 1101
2025-07-02 04:52:33.139 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.139 blo = 351, bhi = 1101
2025-07-02 04:52:33.139
2025-07-02 04:52:33.139 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.139 r"""
2025-07-02 04:52:33.139 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.139 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.139 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.140 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.140
2025-07-02 04:52:33.140 Example:
2025-07-02 04:52:33.140
2025-07-02 04:52:33.140 >>> d = Differ()
2025-07-02 04:52:33.140 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.140 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.140 >>> print(''.join(results), end="")
2025-07-02 04:52:33.140 - abcDefghiJkl
2025-07-02 04:52:33.140 + abcdefGhijkl
2025-07-02 04:52:33.140 """
2025-07-02 04:52:33.140
2025-07-02 04:52:33.140 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.140 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.140 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.140 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.140 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.140
2025-07-02 04:52:33.140 # search for the pair that matches best without being identical
2025-07-02 04:52:33.141 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.141 # on junk -- unless we have to)
2025-07-02 04:52:33.141 for j in range(blo, bhi):
2025-07-02 04:52:33.141 bj = b[j]
2025-07-02 04:52:33.141 cruncher.set_seq2(bj)
2025-07-02 04:52:33.141 for i in range(alo, ahi):
2025-07-02 04:52:33.141 ai = a[i]
2025-07-02 04:52:33.141 if ai == bj:
2025-07-02 04:52:33.141 if eqi is None:
2025-07-02 04:52:33.141 eqi, eqj = i, j
2025-07-02 04:52:33.141 continue
2025-07-02 04:52:33.141 cruncher.set_seq1(ai)
2025-07-02 04:52:33.141 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.141 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.141 # compares by a factor of 3.
2025-07-02 04:52:33.141 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.141 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.141 # of the computation is cached by cruncher
2025-07-02 04:52:33.141 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.141 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.142 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.142 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.142 if best_ratio < cutoff:
2025-07-02 04:52:33.142 # no non-identical "pretty close" pair
2025-07-02 04:52:33.142 if eqi is None:
2025-07-02 04:52:33.142 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.142 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.142 return
2025-07-02 04:52:33.142 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.142 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.142 else:
2025-07-02 04:52:33.142 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.142 eqi = None
2025-07-02 04:52:33.142
2025-07-02 04:52:33.142 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.142 # identical
2025-07-02 04:52:33.142
2025-07-02 04:52:33.142 # pump out diffs from before the synch point
2025-07-02 04:52:33.142 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.142
2025-07-02 04:52:33.142 # do intraline marking on the synch pair
2025-07-02 04:52:33.143 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.143 if eqi is None:
2025-07-02 04:52:33.143 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.143 atags = btags = ""
2025-07-02 04:52:33.143 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.143 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.143 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.143 if tag == 'replace':
2025-07-02 04:52:33.143 atags += '^' * la
2025-07-02 04:52:33.143 btags += '^' * lb
2025-07-02 04:52:33.143 elif tag == 'delete':
2025-07-02 04:52:33.143 atags += '-' * la
2025-07-02 04:52:33.143 elif tag == 'insert':
2025-07-02 04:52:33.143 btags += '+' * lb
2025-07-02 04:52:33.143 elif tag == 'equal':
2025-07-02 04:52:33.143 atags += ' ' * la
2025-07-02 04:52:33.143 btags += ' ' * lb
2025-07-02 04:52:33.143 else:
2025-07-02 04:52:33.143 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.143 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.143 else:
2025-07-02 04:52:33.144 # the synch pair is identical
2025-07-02 04:52:33.144 yield ' ' + aelt
2025-07-02 04:52:33.144
2025-07-02 04:52:33.144 # pump out diffs from after the synch point
2025-07-02 04:52:33.144 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.144
2025-07-02 04:52:33.144 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.144 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.144
2025-07-02 04:52:33.144 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.144 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.144 alo = 352, ahi = 1101
2025-07-02 04:52:33.144 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.144 blo = 352, bhi = 1101
2025-07-02 04:52:33.144
2025-07-02 04:52:33.144 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.144 g = []
2025-07-02 04:52:33.144 if alo < ahi:
2025-07-02 04:52:33.144 if blo < bhi:
2025-07-02 04:52:33.144 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.144 else:
2025-07-02 04:52:33.145 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.145 elif blo < bhi:
2025-07-02 04:52:33.145 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.145
2025-07-02 04:52:33.145 > yield from g
2025-07-02 04:52:33.145
2025-07-02 04:52:33.145 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.145 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.145
2025-07-02 04:52:33.145 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.145 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.145 alo = 352, ahi = 1101
2025-07-02 04:52:33.145 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.145 blo = 352, bhi = 1101
2025-07-02 04:52:33.145
2025-07-02 04:52:33.145 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.145 r"""
2025-07-02 04:52:33.145 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.145 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.146 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.146 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.146
2025-07-02 04:52:33.146 Example:
2025-07-02 04:52:33.146
2025-07-02 04:52:33.146 >>> d = Differ()
2025-07-02 04:52:33.146 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.146 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.146 >>> print(''.join(results), end="")
2025-07-02 04:52:33.146 - abcDefghiJkl
2025-07-02 04:52:33.146 + abcdefGhijkl
2025-07-02 04:52:33.146 """
2025-07-02 04:52:33.146
2025-07-02 04:52:33.146 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.146 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.146 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.146 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.146 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.146
2025-07-02 04:52:33.147 # search for the pair that matches best without being identical
2025-07-02 04:52:33.147 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.147 # on junk -- unless we have to)
2025-07-02 04:52:33.147 for j in range(blo, bhi):
2025-07-02 04:52:33.147 bj = b[j]
2025-07-02 04:52:33.147 cruncher.set_seq2(bj)
2025-07-02 04:52:33.147 for i in range(alo, ahi):
2025-07-02 04:52:33.147 ai = a[i]
2025-07-02 04:52:33.147 if ai == bj:
2025-07-02 04:52:33.147 if eqi is None:
2025-07-02 04:52:33.147 eqi, eqj = i, j
2025-07-02 04:52:33.147 continue
2025-07-02 04:52:33.147 cruncher.set_seq1(ai)
2025-07-02 04:52:33.147 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.147 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.147 # compares by a factor of 3.
2025-07-02 04:52:33.147 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.147 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.147 # of the computation is cached by cruncher
2025-07-02 04:52:33.147 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.148 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.148 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.148 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.148 if best_ratio < cutoff:
2025-07-02 04:52:33.148 # no non-identical "pretty close" pair
2025-07-02 04:52:33.148 if eqi is None:
2025-07-02 04:52:33.148 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.148 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.148 return
2025-07-02 04:52:33.148 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.148 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.148 else:
2025-07-02 04:52:33.148 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.148 eqi = None
2025-07-02 04:52:33.148
2025-07-02 04:52:33.148 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.148 # identical
2025-07-02 04:52:33.148
2025-07-02 04:52:33.148 # pump out diffs from before the synch point
2025-07-02 04:52:33.148 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.149
2025-07-02 04:52:33.149 # do intraline marking on the synch pair
2025-07-02 04:52:33.149 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.149 if eqi is None:
2025-07-02 04:52:33.149 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.149 atags = btags = ""
2025-07-02 04:52:33.149 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.149 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.149 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.149 if tag == 'replace':
2025-07-02 04:52:33.149 atags += '^' * la
2025-07-02 04:52:33.149 btags += '^' * lb
2025-07-02 04:52:33.149 elif tag == 'delete':
2025-07-02 04:52:33.149 atags += '-' * la
2025-07-02 04:52:33.149 elif tag == 'insert':
2025-07-02 04:52:33.149 btags += '+' * lb
2025-07-02 04:52:33.149 elif tag == 'equal':
2025-07-02 04:52:33.149 atags += ' ' * la
2025-07-02 04:52:33.149 btags += ' ' * lb
2025-07-02 04:52:33.149 else:
2025-07-02 04:52:33.149 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.149 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.150 else:
2025-07-02 04:52:33.150 # the synch pair is identical
2025-07-02 04:52:33.150 yield ' ' + aelt
2025-07-02 04:52:33.150
2025-07-02 04:52:33.150 # pump out diffs from after the synch point
2025-07-02 04:52:33.150 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.150
2025-07-02 04:52:33.150 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.150 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.150
2025-07-02 04:52:33.150 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.150 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.150 alo = 353, ahi = 1101
2025-07-02 04:52:33.150 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.150 blo = 353, bhi = 1101
2025-07-02 04:52:33.150
2025-07-02 04:52:33.150 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.150 g = []
2025-07-02 04:52:33.150 if alo < ahi:
2025-07-02 04:52:33.150 if blo < bhi:
2025-07-02 04:52:33.150 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.151 else:
2025-07-02 04:52:33.151 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.151 elif blo < bhi:
2025-07-02 04:52:33.151 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.151
2025-07-02 04:52:33.151 > yield from g
2025-07-02 04:52:33.151
2025-07-02 04:52:33.151 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.151 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.151
2025-07-02 04:52:33.151 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.151 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.151 alo = 353, ahi = 1101
2025-07-02 04:52:33.151 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.151 blo = 353, bhi = 1101
2025-07-02 04:52:33.151
2025-07-02 04:52:33.151 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.151 r"""
2025-07-02 04:52:33.151 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.151 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.151 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.152 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.152
2025-07-02 04:52:33.152 Example:
2025-07-02 04:52:33.152
2025-07-02 04:52:33.152 >>> d = Differ()
2025-07-02 04:52:33.152 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.152 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.152 >>> print(''.join(results), end="")
2025-07-02 04:52:33.152 - abcDefghiJkl
2025-07-02 04:52:33.152 + abcdefGhijkl
2025-07-02 04:52:33.152 """
2025-07-02 04:52:33.152
2025-07-02 04:52:33.152 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.152 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.152 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.152 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.152 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.152
2025-07-02 04:52:33.152 # search for the pair that matches best without being identical
2025-07-02 04:52:33.153 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.153 # on junk -- unless we have to)
2025-07-02 04:52:33.153 for j in range(blo, bhi):
2025-07-02 04:52:33.153 bj = b[j]
2025-07-02 04:52:33.153 cruncher.set_seq2(bj)
2025-07-02 04:52:33.153 for i in range(alo, ahi):
2025-07-02 04:52:33.153 ai = a[i]
2025-07-02 04:52:33.153 if ai == bj:
2025-07-02 04:52:33.153 if eqi is None:
2025-07-02 04:52:33.153 eqi, eqj = i, j
2025-07-02 04:52:33.153 continue
2025-07-02 04:52:33.153 cruncher.set_seq1(ai)
2025-07-02 04:52:33.153 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.153 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.153 # compares by a factor of 3.
2025-07-02 04:52:33.153 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.153 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.153 # of the computation is cached by cruncher
2025-07-02 04:52:33.153 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.153 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.153 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.153 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.154 if best_ratio < cutoff:
2025-07-02 04:52:33.154 # no non-identical "pretty close" pair
2025-07-02 04:52:33.154 if eqi is None:
2025-07-02 04:52:33.154 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.154 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.154 return
2025-07-02 04:52:33.154 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.154 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.154 else:
2025-07-02 04:52:33.154 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.154 eqi = None
2025-07-02 04:52:33.154
2025-07-02 04:52:33.154 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.154 # identical
2025-07-02 04:52:33.154
2025-07-02 04:52:33.154 # pump out diffs from before the synch point
2025-07-02 04:52:33.154 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.154
2025-07-02 04:52:33.154 # do intraline marking on the synch pair
2025-07-02 04:52:33.154 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.154 if eqi is None:
2025-07-02 04:52:33.155 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.155 atags = btags = ""
2025-07-02 04:52:33.155 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.155 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.155 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.155 if tag == 'replace':
2025-07-02 04:52:33.155 atags += '^' * la
2025-07-02 04:52:33.155 btags += '^' * lb
2025-07-02 04:52:33.155 elif tag == 'delete':
2025-07-02 04:52:33.155 atags += '-' * la
2025-07-02 04:52:33.155 elif tag == 'insert':
2025-07-02 04:52:33.155 btags += '+' * lb
2025-07-02 04:52:33.155 elif tag == 'equal':
2025-07-02 04:52:33.155 atags += ' ' * la
2025-07-02 04:52:33.155 btags += ' ' * lb
2025-07-02 04:52:33.155 else:
2025-07-02 04:52:33.155 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.155 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.155 else:
2025-07-02 04:52:33.155 # the synch pair is identical
2025-07-02 04:52:33.155 yield ' ' + aelt
2025-07-02 04:52:33.156
2025-07-02 04:52:33.156 # pump out diffs from after the synch point
2025-07-02 04:52:33.156 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.156
2025-07-02 04:52:33.156 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.156 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.156
2025-07-02 04:52:33.156 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.156 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.156 alo = 356, ahi = 1101
2025-07-02 04:52:33.156 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.156 blo = 356, bhi = 1101
2025-07-02 04:52:33.156
2025-07-02 04:52:33.156 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.156 g = []
2025-07-02 04:52:33.156 if alo < ahi:
2025-07-02 04:52:33.156 if blo < bhi:
2025-07-02 04:52:33.156 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.156 else:
2025-07-02 04:52:33.156 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.157 elif blo < bhi:
2025-07-02 04:52:33.157 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.157
2025-07-02 04:52:33.157 > yield from g
2025-07-02 04:52:33.157
2025-07-02 04:52:33.157 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.157 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.157
2025-07-02 04:52:33.157 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.157 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.157 alo = 356, ahi = 1101
2025-07-02 04:52:33.157 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.157 blo = 356, bhi = 1101
2025-07-02 04:52:33.157
2025-07-02 04:52:33.157 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.157 r"""
2025-07-02 04:52:33.157 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.157 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.157 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.157 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.158
2025-07-02 04:52:33.158 Example:
2025-07-02 04:52:33.158
2025-07-02 04:52:33.158 >>> d = Differ()
2025-07-02 04:52:33.158 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.158 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.158 >>> print(''.join(results), end="")
2025-07-02 04:52:33.158 - abcDefghiJkl
2025-07-02 04:52:33.158 + abcdefGhijkl
2025-07-02 04:52:33.158 """
2025-07-02 04:52:33.158
2025-07-02 04:52:33.158 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.158 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.158 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.158 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.158 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.158
2025-07-02 04:52:33.158 # search for the pair that matches best without being identical
2025-07-02 04:52:33.158 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.158 # on junk -- unless we have to)
2025-07-02 04:52:33.159 for j in range(blo, bhi):
2025-07-02 04:52:33.159 bj = b[j]
2025-07-02 04:52:33.159 cruncher.set_seq2(bj)
2025-07-02 04:52:33.159 for i in range(alo, ahi):
2025-07-02 04:52:33.159 ai = a[i]
2025-07-02 04:52:33.159 if ai == bj:
2025-07-02 04:52:33.159 if eqi is None:
2025-07-02 04:52:33.159 eqi, eqj = i, j
2025-07-02 04:52:33.159 continue
2025-07-02 04:52:33.159 cruncher.set_seq1(ai)
2025-07-02 04:52:33.159 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.159 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.159 # compares by a factor of 3.
2025-07-02 04:52:33.159 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.159 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.159 # of the computation is cached by cruncher
2025-07-02 04:52:33.159 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.159 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.159 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.159 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.159 if best_ratio < cutoff:
2025-07-02 04:52:33.160 # no non-identical "pretty close" pair
2025-07-02 04:52:33.160 if eqi is None:
2025-07-02 04:52:33.160 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.160 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.160 return
2025-07-02 04:52:33.160 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.160 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.160 else:
2025-07-02 04:52:33.160 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.160 eqi = None
2025-07-02 04:52:33.160
2025-07-02 04:52:33.160 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.160 # identical
2025-07-02 04:52:33.160
2025-07-02 04:52:33.160 # pump out diffs from before the synch point
2025-07-02 04:52:33.160 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.160
2025-07-02 04:52:33.160 # do intraline marking on the synch pair
2025-07-02 04:52:33.160 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.161 if eqi is None:
2025-07-02 04:52:33.161 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.161 atags = btags = ""
2025-07-02 04:52:33.161 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.161 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.161 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.161 if tag == 'replace':
2025-07-02 04:52:33.161 atags += '^' * la
2025-07-02 04:52:33.161 btags += '^' * lb
2025-07-02 04:52:33.161 elif tag == 'delete':
2025-07-02 04:52:33.161 atags += '-' * la
2025-07-02 04:52:33.161 elif tag == 'insert':
2025-07-02 04:52:33.161 btags += '+' * lb
2025-07-02 04:52:33.161 elif tag == 'equal':
2025-07-02 04:52:33.161 atags += ' ' * la
2025-07-02 04:52:33.161 btags += ' ' * lb
2025-07-02 04:52:33.161 else:
2025-07-02 04:52:33.161 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.161 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.161 else:
2025-07-02 04:52:33.162 # the synch pair is identical
2025-07-02 04:52:33.162 yield ' ' + aelt
2025-07-02 04:52:33.162
2025-07-02 04:52:33.162 # pump out diffs from after the synch point
2025-07-02 04:52:33.162 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.162
2025-07-02 04:52:33.162 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.162 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.162
2025-07-02 04:52:33.162 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.162 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.162 alo = 357, ahi = 1101
2025-07-02 04:52:33.162 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.162 blo = 357, bhi = 1101
2025-07-02 04:52:33.162
2025-07-02 04:52:33.162 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.162 g = []
2025-07-02 04:52:33.162 if alo < ahi:
2025-07-02 04:52:33.162 if blo < bhi:
2025-07-02 04:52:33.162 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.162 else:
2025-07-02 04:52:33.163 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.163 elif blo < bhi:
2025-07-02 04:52:33.163 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.163
2025-07-02 04:52:33.163 > yield from g
2025-07-02 04:52:33.163
2025-07-02 04:52:33.163 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.163 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.163
2025-07-02 04:52:33.163 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.163 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.163 alo = 357, ahi = 1101
2025-07-02 04:52:33.163 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.163 blo = 357, bhi = 1101
2025-07-02 04:52:33.163
2025-07-02 04:52:33.163 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.163 r"""
2025-07-02 04:52:33.163 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.164 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.164 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.164 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.164
2025-07-02 04:52:33.164 Example:
2025-07-02 04:52:33.164
2025-07-02 04:52:33.164 >>> d = Differ()
2025-07-02 04:52:33.164 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.164 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.164 >>> print(''.join(results), end="")
2025-07-02 04:52:33.164 - abcDefghiJkl
2025-07-02 04:52:33.164 + abcdefGhijkl
2025-07-02 04:52:33.164 """
2025-07-02 04:52:33.164
2025-07-02 04:52:33.164 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.164 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.164 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.164 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.165 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.165
2025-07-02 04:52:33.165 # search for the pair that matches best without being identical
2025-07-02 04:52:33.165 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.165 # on junk -- unless we have to)
2025-07-02 04:52:33.165 for j in range(blo, bhi):
2025-07-02 04:52:33.165 bj = b[j]
2025-07-02 04:52:33.165 cruncher.set_seq2(bj)
2025-07-02 04:52:33.165 for i in range(alo, ahi):
2025-07-02 04:52:33.165 ai = a[i]
2025-07-02 04:52:33.165 if ai == bj:
2025-07-02 04:52:33.165 if eqi is None:
2025-07-02 04:52:33.165 eqi, eqj = i, j
2025-07-02 04:52:33.165 continue
2025-07-02 04:52:33.165 cruncher.set_seq1(ai)
2025-07-02 04:52:33.165 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.165 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.165 # compares by a factor of 3.
2025-07-02 04:52:33.165 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.165 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.166 # of the computation is cached by cruncher
2025-07-02 04:52:33.166 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.166 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.166 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.166 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.166 if best_ratio < cutoff:
2025-07-02 04:52:33.166 # no non-identical "pretty close" pair
2025-07-02 04:52:33.166 if eqi is None:
2025-07-02 04:52:33.166 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.166 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.166 return
2025-07-02 04:52:33.166 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.166 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.166 else:
2025-07-02 04:52:33.166 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.166 eqi = None
2025-07-02 04:52:33.166
2025-07-02 04:52:33.166 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.166 # identical
2025-07-02 04:52:33.166
2025-07-02 04:52:33.166 # pump out diffs from before the synch point
2025-07-02 04:52:33.167 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.167
2025-07-02 04:52:33.167 # do intraline marking on the synch pair
2025-07-02 04:52:33.167 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.167 if eqi is None:
2025-07-02 04:52:33.167 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.167 atags = btags = ""
2025-07-02 04:52:33.167 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.167 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.167 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.167 if tag == 'replace':
2025-07-02 04:52:33.167 atags += '^' * la
2025-07-02 04:52:33.167 btags += '^' * lb
2025-07-02 04:52:33.167 elif tag == 'delete':
2025-07-02 04:52:33.167 atags += '-' * la
2025-07-02 04:52:33.167 elif tag == 'insert':
2025-07-02 04:52:33.167 btags += '+' * lb
2025-07-02 04:52:33.167 elif tag == 'equal':
2025-07-02 04:52:33.167 atags += ' ' * la
2025-07-02 04:52:33.167 btags += ' ' * lb
2025-07-02 04:52:33.167 else:
2025-07-02 04:52:33.168 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.168 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.168 else:
2025-07-02 04:52:33.168 # the synch pair is identical
2025-07-02 04:52:33.168 yield ' ' + aelt
2025-07-02 04:52:33.168
2025-07-02 04:52:33.168 # pump out diffs from after the synch point
2025-07-02 04:52:33.168 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.168
2025-07-02 04:52:33.168 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.168 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.168
2025-07-02 04:52:33.168 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.168 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.168 alo = 358, ahi = 1101
2025-07-02 04:52:33.168 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.168 blo = 358, bhi = 1101
2025-07-02 04:52:33.168
2025-07-02 04:52:33.168 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.168 g = []
2025-07-02 04:52:33.168 if alo < ahi:
2025-07-02 04:52:33.169 if blo < bhi:
2025-07-02 04:52:33.169 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.169 else:
2025-07-02 04:52:33.169 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.169 elif blo < bhi:
2025-07-02 04:52:33.169 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.169
2025-07-02 04:52:33.169 > yield from g
2025-07-02 04:52:33.169
2025-07-02 04:52:33.169 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.169 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.169
2025-07-02 04:52:33.169 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.169 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.169 alo = 358, ahi = 1101
2025-07-02 04:52:33.169 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.169 blo = 358, bhi = 1101
2025-07-02 04:52:33.169
2025-07-02 04:52:33.169 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.169 r"""
2025-07-02 04:52:33.169 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.170 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.170 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.170 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.170
2025-07-02 04:52:33.170 Example:
2025-07-02 04:52:33.170
2025-07-02 04:52:33.170 >>> d = Differ()
2025-07-02 04:52:33.170 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.170 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.170 >>> print(''.join(results), end="")
2025-07-02 04:52:33.170 - abcDefghiJkl
2025-07-02 04:52:33.170 + abcdefGhijkl
2025-07-02 04:52:33.170 """
2025-07-02 04:52:33.170
2025-07-02 04:52:33.170 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.170 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.170 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.170 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.170 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.171
2025-07-02 04:52:33.171 # search for the pair that matches best without being identical
2025-07-02 04:52:33.171 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.171 # on junk -- unless we have to)
2025-07-02 04:52:33.171 for j in range(blo, bhi):
2025-07-02 04:52:33.171 bj = b[j]
2025-07-02 04:52:33.171 cruncher.set_seq2(bj)
2025-07-02 04:52:33.171 for i in range(alo, ahi):
2025-07-02 04:52:33.171 ai = a[i]
2025-07-02 04:52:33.171 if ai == bj:
2025-07-02 04:52:33.171 if eqi is None:
2025-07-02 04:52:33.171 eqi, eqj = i, j
2025-07-02 04:52:33.171 continue
2025-07-02 04:52:33.171 cruncher.set_seq1(ai)
2025-07-02 04:52:33.171 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.171 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.171 # compares by a factor of 3.
2025-07-02 04:52:33.171 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.171 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.171 # of the computation is cached by cruncher
2025-07-02 04:52:33.171 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.172 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.172 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.172 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.172 if best_ratio < cutoff:
2025-07-02 04:52:33.172 # no non-identical "pretty close" pair
2025-07-02 04:52:33.172 if eqi is None:
2025-07-02 04:52:33.172 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.172 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.172 return
2025-07-02 04:52:33.172 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.172 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.172 else:
2025-07-02 04:52:33.172 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.172 eqi = None
2025-07-02 04:52:33.172
2025-07-02 04:52:33.172 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.172 # identical
2025-07-02 04:52:33.172
2025-07-02 04:52:33.172 # pump out diffs from before the synch point
2025-07-02 04:52:33.173 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.173
2025-07-02 04:52:33.173 # do intraline marking on the synch pair
2025-07-02 04:52:33.173 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.173 if eqi is None:
2025-07-02 04:52:33.173 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.173 atags = btags = ""
2025-07-02 04:52:33.173 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.173 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.173 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.173 if tag == 'replace':
2025-07-02 04:52:33.173 atags += '^' * la
2025-07-02 04:52:33.173 btags += '^' * lb
2025-07-02 04:52:33.173 elif tag == 'delete':
2025-07-02 04:52:33.173 atags += '-' * la
2025-07-02 04:52:33.173 elif tag == 'insert':
2025-07-02 04:52:33.173 btags += '+' * lb
2025-07-02 04:52:33.173 elif tag == 'equal':
2025-07-02 04:52:33.173 atags += ' ' * la
2025-07-02 04:52:33.173 btags += ' ' * lb
2025-07-02 04:52:33.174 else:
2025-07-02 04:52:33.174 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.174 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.174 else:
2025-07-02 04:52:33.174 # the synch pair is identical
2025-07-02 04:52:33.174 yield ' ' + aelt
2025-07-02 04:52:33.174
2025-07-02 04:52:33.174 # pump out diffs from after the synch point
2025-07-02 04:52:33.174 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.174
2025-07-02 04:52:33.174 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.174 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.174
2025-07-02 04:52:33.174 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.174 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.174 alo = 359, ahi = 1101
2025-07-02 04:52:33.174 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.174 blo = 359, bhi = 1101
2025-07-02 04:52:33.174
2025-07-02 04:52:33.174 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.174 g = []
2025-07-02 04:52:33.175 if alo < ahi:
2025-07-02 04:52:33.175 if blo < bhi:
2025-07-02 04:52:33.175 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.175 else:
2025-07-02 04:52:33.175 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.175 elif blo < bhi:
2025-07-02 04:52:33.175 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.175
2025-07-02 04:52:33.175 > yield from g
2025-07-02 04:52:33.175
2025-07-02 04:52:33.175 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.175 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.175
2025-07-02 04:52:33.175 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.175 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.175 alo = 359, ahi = 1101
2025-07-02 04:52:33.175 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.175 blo = 359, bhi = 1101
2025-07-02 04:52:33.175
2025-07-02 04:52:33.175 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.175 r"""
2025-07-02 04:52:33.176 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.176 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.176 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.176 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.176
2025-07-02 04:52:33.176 Example:
2025-07-02 04:52:33.176
2025-07-02 04:52:33.176 >>> d = Differ()
2025-07-02 04:52:33.176 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.176 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.176 >>> print(''.join(results), end="")
2025-07-02 04:52:33.176 - abcDefghiJkl
2025-07-02 04:52:33.176 + abcdefGhijkl
2025-07-02 04:52:33.176 """
2025-07-02 04:52:33.176
2025-07-02 04:52:33.176 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.176 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.176 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.177 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.177 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.177
2025-07-02 04:52:33.177 # search for the pair that matches best without being identical
2025-07-02 04:52:33.177 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.177 # on junk -- unless we have to)
2025-07-02 04:52:33.177 for j in range(blo, bhi):
2025-07-02 04:52:33.177 bj = b[j]
2025-07-02 04:52:33.177 cruncher.set_seq2(bj)
2025-07-02 04:52:33.177 for i in range(alo, ahi):
2025-07-02 04:52:33.177 ai = a[i]
2025-07-02 04:52:33.177 if ai == bj:
2025-07-02 04:52:33.177 if eqi is None:
2025-07-02 04:52:33.177 eqi, eqj = i, j
2025-07-02 04:52:33.177 continue
2025-07-02 04:52:33.177 cruncher.set_seq1(ai)
2025-07-02 04:52:33.177 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.177 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.177 # compares by a factor of 3.
2025-07-02 04:52:33.177 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.177 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.178 # of the computation is cached by cruncher
2025-07-02 04:52:33.178 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.178 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.178 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.178 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.178 if best_ratio < cutoff:
2025-07-02 04:52:33.178 # no non-identical "pretty close" pair
2025-07-02 04:52:33.178 if eqi is None:
2025-07-02 04:52:33.178 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.178 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.178 return
2025-07-02 04:52:33.178 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.178 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.178 else:
2025-07-02 04:52:33.178 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.178 eqi = None
2025-07-02 04:52:33.178
2025-07-02 04:52:33.178 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.178 # identical
2025-07-02 04:52:33.178
2025-07-02 04:52:33.178 # pump out diffs from before the synch point
2025-07-02 04:52:33.179 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.179
2025-07-02 04:52:33.179 # do intraline marking on the synch pair
2025-07-02 04:52:33.179 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.179 if eqi is None:
2025-07-02 04:52:33.179 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.179 atags = btags = ""
2025-07-02 04:52:33.179 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.179 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.179 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.179 if tag == 'replace':
2025-07-02 04:52:33.179 atags += '^' * la
2025-07-02 04:52:33.179 btags += '^' * lb
2025-07-02 04:52:33.179 elif tag == 'delete':
2025-07-02 04:52:33.179 atags += '-' * la
2025-07-02 04:52:33.179 elif tag == 'insert':
2025-07-02 04:52:33.179 btags += '+' * lb
2025-07-02 04:52:33.179 elif tag == 'equal':
2025-07-02 04:52:33.179 atags += ' ' * la
2025-07-02 04:52:33.179 btags += ' ' * lb
2025-07-02 04:52:33.179 else:
2025-07-02 04:52:33.179 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.180 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.180 else:
2025-07-02 04:52:33.180 # the synch pair is identical
2025-07-02 04:52:33.180 yield ' ' + aelt
2025-07-02 04:52:33.180
2025-07-02 04:52:33.180 # pump out diffs from after the synch point
2025-07-02 04:52:33.180 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.180
2025-07-02 04:52:33.180 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.180 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.180
2025-07-02 04:52:33.180 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.180 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.180 alo = 360, ahi = 1101
2025-07-02 04:52:33.180 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.180 blo = 360, bhi = 1101
2025-07-02 04:52:33.180
2025-07-02 04:52:33.180 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.180 g = []
2025-07-02 04:52:33.180 if alo < ahi:
2025-07-02 04:52:33.181 if blo < bhi:
2025-07-02 04:52:33.181 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.181 else:
2025-07-02 04:52:33.181 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.181 elif blo < bhi:
2025-07-02 04:52:33.181 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.181
2025-07-02 04:52:33.181 > yield from g
2025-07-02 04:52:33.181
2025-07-02 04:52:33.181 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.181 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.181
2025-07-02 04:52:33.181 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.181 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.181 alo = 360, ahi = 1101
2025-07-02 04:52:33.181 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.181 blo = 360, bhi = 1101
2025-07-02 04:52:33.181
2025-07-02 04:52:33.181 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.181 r"""
2025-07-02 04:52:33.182 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.182 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.182 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.182 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.182
2025-07-02 04:52:33.182 Example:
2025-07-02 04:52:33.182
2025-07-02 04:52:33.182 >>> d = Differ()
2025-07-02 04:52:33.182 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.182 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.182 >>> print(''.join(results), end="")
2025-07-02 04:52:33.182 - abcDefghiJkl
2025-07-02 04:52:33.182 + abcdefGhijkl
2025-07-02 04:52:33.182 """
2025-07-02 04:52:33.182
2025-07-02 04:52:33.182 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.182 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.182 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.182 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.183 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.183
2025-07-02 04:52:33.183 # search for the pair that matches best without being identical
2025-07-02 04:52:33.183 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.183 # on junk -- unless we have to)
2025-07-02 04:52:33.183 for j in range(blo, bhi):
2025-07-02 04:52:33.183 bj = b[j]
2025-07-02 04:52:33.183 cruncher.set_seq2(bj)
2025-07-02 04:52:33.183 for i in range(alo, ahi):
2025-07-02 04:52:33.183 ai = a[i]
2025-07-02 04:52:33.183 if ai == bj:
2025-07-02 04:52:33.183 if eqi is None:
2025-07-02 04:52:33.183 eqi, eqj = i, j
2025-07-02 04:52:33.183 continue
2025-07-02 04:52:33.183 cruncher.set_seq1(ai)
2025-07-02 04:52:33.183 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.183 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.183 # compares by a factor of 3.
2025-07-02 04:52:33.183 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.183 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.183 # of the computation is cached by cruncher
2025-07-02 04:52:33.184 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.184 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.184 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.184 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.184 if best_ratio < cutoff:
2025-07-02 04:52:33.184 # no non-identical "pretty close" pair
2025-07-02 04:52:33.184 if eqi is None:
2025-07-02 04:52:33.184 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.184 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.184 return
2025-07-02 04:52:33.184 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.184 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.184 else:
2025-07-02 04:52:33.184 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.184 eqi = None
2025-07-02 04:52:33.184
2025-07-02 04:52:33.184 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.184 # identical
2025-07-02 04:52:33.184
2025-07-02 04:52:33.184 # pump out diffs from before the synch point
2025-07-02 04:52:33.184 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.184
2025-07-02 04:52:33.185 # do intraline marking on the synch pair
2025-07-02 04:52:33.185 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.185 if eqi is None:
2025-07-02 04:52:33.185 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.185 atags = btags = ""
2025-07-02 04:52:33.185 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.185 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.185 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.185 if tag == 'replace':
2025-07-02 04:52:33.185 atags += '^' * la
2025-07-02 04:52:33.185 btags += '^' * lb
2025-07-02 04:52:33.185 elif tag == 'delete':
2025-07-02 04:52:33.185 atags += '-' * la
2025-07-02 04:52:33.185 elif tag == 'insert':
2025-07-02 04:52:33.185 btags += '+' * lb
2025-07-02 04:52:33.185 elif tag == 'equal':
2025-07-02 04:52:33.185 atags += ' ' * la
2025-07-02 04:52:33.185 btags += ' ' * lb
2025-07-02 04:52:33.185 else:
2025-07-02 04:52:33.185 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.185 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.186 else:
2025-07-02 04:52:33.186 # the synch pair is identical
2025-07-02 04:52:33.186 yield ' ' + aelt
2025-07-02 04:52:33.186
2025-07-02 04:52:33.186 # pump out diffs from after the synch point
2025-07-02 04:52:33.186 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.186
2025-07-02 04:52:33.186 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.186 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.186
2025-07-02 04:52:33.186 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.186 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.186 alo = 361, ahi = 1101
2025-07-02 04:52:33.186 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.186 blo = 361, bhi = 1101
2025-07-02 04:52:33.186
2025-07-02 04:52:33.186 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.186 g = []
2025-07-02 04:52:33.186 if alo < ahi:
2025-07-02 04:52:33.186 if blo < bhi:
2025-07-02 04:52:33.186 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.186 else:
2025-07-02 04:52:33.187 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.187 elif blo < bhi:
2025-07-02 04:52:33.187 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.187
2025-07-02 04:52:33.187 > yield from g
2025-07-02 04:52:33.187
2025-07-02 04:52:33.187 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.187 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.187
2025-07-02 04:52:33.187 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.187 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.187 alo = 361, ahi = 1101
2025-07-02 04:52:33.187 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.187 blo = 361, bhi = 1101
2025-07-02 04:52:33.187
2025-07-02 04:52:33.187 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.187 r"""
2025-07-02 04:52:33.187 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.187 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.187 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.187 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.188
2025-07-02 04:52:33.188 Example:
2025-07-02 04:52:33.188
2025-07-02 04:52:33.188 >>> d = Differ()
2025-07-02 04:52:33.188 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.188 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.188 >>> print(''.join(results), end="")
2025-07-02 04:52:33.188 - abcDefghiJkl
2025-07-02 04:52:33.188 + abcdefGhijkl
2025-07-02 04:52:33.188 """
2025-07-02 04:52:33.188
2025-07-02 04:52:33.188 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.188 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.188 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.188 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.188 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.188
2025-07-02 04:52:33.188 # search for the pair that matches best without being identical
2025-07-02 04:52:33.189 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.189 # on junk -- unless we have to)
2025-07-02 04:52:33.189 for j in range(blo, bhi):
2025-07-02 04:52:33.189 bj = b[j]
2025-07-02 04:52:33.189 cruncher.set_seq2(bj)
2025-07-02 04:52:33.189 for i in range(alo, ahi):
2025-07-02 04:52:33.189 ai = a[i]
2025-07-02 04:52:33.189 if ai == bj:
2025-07-02 04:52:33.189 if eqi is None:
2025-07-02 04:52:33.189 eqi, eqj = i, j
2025-07-02 04:52:33.189 continue
2025-07-02 04:52:33.189 cruncher.set_seq1(ai)
2025-07-02 04:52:33.189 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.189 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.189 # compares by a factor of 3.
2025-07-02 04:52:33.189 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.189 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.189 # of the computation is cached by cruncher
2025-07-02 04:52:33.189 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.189 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.189 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.190 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.190 if best_ratio < cutoff:
2025-07-02 04:52:33.190 # no non-identical "pretty close" pair
2025-07-02 04:52:33.190 if eqi is None:
2025-07-02 04:52:33.190 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.190 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.190 return
2025-07-02 04:52:33.190 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.190 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.190 else:
2025-07-02 04:52:33.190 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.190 eqi = None
2025-07-02 04:52:33.190
2025-07-02 04:52:33.190 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.190 # identical
2025-07-02 04:52:33.190
2025-07-02 04:52:33.190 # pump out diffs from before the synch point
2025-07-02 04:52:33.190 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.190
2025-07-02 04:52:33.190 # do intraline marking on the synch pair
2025-07-02 04:52:33.190 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.191 if eqi is None:
2025-07-02 04:52:33.191 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.191 atags = btags = ""
2025-07-02 04:52:33.191 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.191 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.191 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.191 if tag == 'replace':
2025-07-02 04:52:33.191 atags += '^' * la
2025-07-02 04:52:33.191 btags += '^' * lb
2025-07-02 04:52:33.191 elif tag == 'delete':
2025-07-02 04:52:33.191 atags += '-' * la
2025-07-02 04:52:33.191 elif tag == 'insert':
2025-07-02 04:52:33.191 btags += '+' * lb
2025-07-02 04:52:33.191 elif tag == 'equal':
2025-07-02 04:52:33.191 atags += ' ' * la
2025-07-02 04:52:33.191 btags += ' ' * lb
2025-07-02 04:52:33.191 else:
2025-07-02 04:52:33.191 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.191 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.191 else:
2025-07-02 04:52:33.192 # the synch pair is identical
2025-07-02 04:52:33.192 yield ' ' + aelt
2025-07-02 04:52:33.192
2025-07-02 04:52:33.192 # pump out diffs from after the synch point
2025-07-02 04:52:33.192 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.192
2025-07-02 04:52:33.192 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.192 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.192
2025-07-02 04:52:33.192 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.192 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.192 alo = 362, ahi = 1101
2025-07-02 04:52:33.192 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.192 blo = 362, bhi = 1101
2025-07-02 04:52:33.192
2025-07-02 04:52:33.192 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.192 g = []
2025-07-02 04:52:33.192 if alo < ahi:
2025-07-02 04:52:33.192 if blo < bhi:
2025-07-02 04:52:33.192 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.192 else:
2025-07-02 04:52:33.193 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.193 elif blo < bhi:
2025-07-02 04:52:33.193 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.193
2025-07-02 04:52:33.193 > yield from g
2025-07-02 04:52:33.193
2025-07-02 04:52:33.193 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.193 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.193
2025-07-02 04:52:33.193 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.193 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.193 alo = 362, ahi = 1101
2025-07-02 04:52:33.193 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.193 blo = 362, bhi = 1101
2025-07-02 04:52:33.193
2025-07-02 04:52:33.193 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.193 r"""
2025-07-02 04:52:33.193 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.193 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.193 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.193 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.194
2025-07-02 04:52:33.194 Example:
2025-07-02 04:52:33.194
2025-07-02 04:52:33.194 >>> d = Differ()
2025-07-02 04:52:33.194 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.194 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.194 >>> print(''.join(results), end="")
2025-07-02 04:52:33.194 - abcDefghiJkl
2025-07-02 04:52:33.194 + abcdefGhijkl
2025-07-02 04:52:33.194 """
2025-07-02 04:52:33.194
2025-07-02 04:52:33.194 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.194 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.194 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.194 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.194 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.194
2025-07-02 04:52:33.194 # search for the pair that matches best without being identical
2025-07-02 04:52:33.194 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.194 # on junk -- unless we have to)
2025-07-02 04:52:33.195 for j in range(blo, bhi):
2025-07-02 04:52:33.195 bj = b[j]
2025-07-02 04:52:33.195 cruncher.set_seq2(bj)
2025-07-02 04:52:33.195 for i in range(alo, ahi):
2025-07-02 04:52:33.195 ai = a[i]
2025-07-02 04:52:33.195 if ai == bj:
2025-07-02 04:52:33.195 if eqi is None:
2025-07-02 04:52:33.195 eqi, eqj = i, j
2025-07-02 04:52:33.195 continue
2025-07-02 04:52:33.195 cruncher.set_seq1(ai)
2025-07-02 04:52:33.195 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.195 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.195 # compares by a factor of 3.
2025-07-02 04:52:33.195 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.195 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.195 # of the computation is cached by cruncher
2025-07-02 04:52:33.195 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.195 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.195 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.195 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.195 if best_ratio < cutoff:
2025-07-02 04:52:33.196 # no non-identical "pretty close" pair
2025-07-02 04:52:33.196 if eqi is None:
2025-07-02 04:52:33.196 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.196 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.196 return
2025-07-02 04:52:33.196 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.196 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.196 else:
2025-07-02 04:52:33.196 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.196 eqi = None
2025-07-02 04:52:33.196
2025-07-02 04:52:33.196 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.196 # identical
2025-07-02 04:52:33.196
2025-07-02 04:52:33.196 # pump out diffs from before the synch point
2025-07-02 04:52:33.196 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.196
2025-07-02 04:52:33.196 # do intraline marking on the synch pair
2025-07-02 04:52:33.196 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.196 if eqi is None:
2025-07-02 04:52:33.196 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.196 atags = btags = ""
2025-07-02 04:52:33.197 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.197 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.197 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.197 if tag == 'replace':
2025-07-02 04:52:33.197 atags += '^' * la
2025-07-02 04:52:33.197 btags += '^' * lb
2025-07-02 04:52:33.197 elif tag == 'delete':
2025-07-02 04:52:33.197 atags += '-' * la
2025-07-02 04:52:33.197 elif tag == 'insert':
2025-07-02 04:52:33.197 btags += '+' * lb
2025-07-02 04:52:33.197 elif tag == 'equal':
2025-07-02 04:52:33.197 atags += ' ' * la
2025-07-02 04:52:33.197 btags += ' ' * lb
2025-07-02 04:52:33.197 else:
2025-07-02 04:52:33.197 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.197 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.197 else:
2025-07-02 04:52:33.197 # the synch pair is identical
2025-07-02 04:52:33.197 yield ' ' + aelt
2025-07-02 04:52:33.198
2025-07-02 04:52:33.198 # pump out diffs from after the synch point
2025-07-02 04:52:33.198 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.198
2025-07-02 04:52:33.198 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.198 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.198
2025-07-02 04:52:33.198 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.198 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.198 alo = 363, ahi = 1101
2025-07-02 04:52:33.198 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.198 blo = 363, bhi = 1101
2025-07-02 04:52:33.198
2025-07-02 04:52:33.198 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.198 g = []
2025-07-02 04:52:33.198 if alo < ahi:
2025-07-02 04:52:33.198 if blo < bhi:
2025-07-02 04:52:33.198 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.198 else:
2025-07-02 04:52:33.198 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.199 elif blo < bhi:
2025-07-02 04:52:33.199 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.199
2025-07-02 04:52:33.199 > yield from g
2025-07-02 04:52:33.199
2025-07-02 04:52:33.199 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.199 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.199
2025-07-02 04:52:33.199 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.199 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.199 alo = 363, ahi = 1101
2025-07-02 04:52:33.199 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.199 blo = 363, bhi = 1101
2025-07-02 04:52:33.199
2025-07-02 04:52:33.199 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.199 r"""
2025-07-02 04:52:33.199 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.199 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.199 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.199 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.199
2025-07-02 04:52:33.200 Example:
2025-07-02 04:52:33.200
2025-07-02 04:52:33.200 >>> d = Differ()
2025-07-02 04:52:33.200 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.200 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.200 >>> print(''.join(results), end="")
2025-07-02 04:52:33.200 - abcDefghiJkl
2025-07-02 04:52:33.200 + abcdefGhijkl
2025-07-02 04:52:33.200 """
2025-07-02 04:52:33.200
2025-07-02 04:52:33.200 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.200 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.200 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.200 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.200 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.200
2025-07-02 04:52:33.200 # search for the pair that matches best without being identical
2025-07-02 04:52:33.200 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.200 # on junk -- unless we have to)
2025-07-02 04:52:33.200 for j in range(blo, bhi):
2025-07-02 04:52:33.201 bj = b[j]
2025-07-02 04:52:33.201 cruncher.set_seq2(bj)
2025-07-02 04:52:33.201 for i in range(alo, ahi):
2025-07-02 04:52:33.201 ai = a[i]
2025-07-02 04:52:33.201 if ai == bj:
2025-07-02 04:52:33.201 if eqi is None:
2025-07-02 04:52:33.201 eqi, eqj = i, j
2025-07-02 04:52:33.201 continue
2025-07-02 04:52:33.201 cruncher.set_seq1(ai)
2025-07-02 04:52:33.201 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.201 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.201 # compares by a factor of 3.
2025-07-02 04:52:33.201 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.201 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.201 # of the computation is cached by cruncher
2025-07-02 04:52:33.201 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.201 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.201 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.201 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.201 if best_ratio < cutoff:
2025-07-02 04:52:33.201 # no non-identical "pretty close" pair
2025-07-02 04:52:33.202 if eqi is None:
2025-07-02 04:52:33.202 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.202 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.202 return
2025-07-02 04:52:33.202 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.202 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.202 else:
2025-07-02 04:52:33.202 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.202 eqi = None
2025-07-02 04:52:33.202
2025-07-02 04:52:33.202 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.202 # identical
2025-07-02 04:52:33.202
2025-07-02 04:52:33.202 # pump out diffs from before the synch point
2025-07-02 04:52:33.202 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.202
2025-07-02 04:52:33.202 # do intraline marking on the synch pair
2025-07-02 04:52:33.202 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.202 if eqi is None:
2025-07-02 04:52:33.202 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.202 atags = btags = ""
2025-07-02 04:52:33.202 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.203 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.203 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.203 if tag == 'replace':
2025-07-02 04:52:33.203 atags += '^' * la
2025-07-02 04:52:33.203 btags += '^' * lb
2025-07-02 04:52:33.203 elif tag == 'delete':
2025-07-02 04:52:33.203 atags += '-' * la
2025-07-02 04:52:33.203 elif tag == 'insert':
2025-07-02 04:52:33.203 btags += '+' * lb
2025-07-02 04:52:33.203 elif tag == 'equal':
2025-07-02 04:52:33.203 atags += ' ' * la
2025-07-02 04:52:33.203 btags += ' ' * lb
2025-07-02 04:52:33.203 else:
2025-07-02 04:52:33.203 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.203 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.203 else:
2025-07-02 04:52:33.203 # the synch pair is identical
2025-07-02 04:52:33.203 yield ' ' + aelt
2025-07-02 04:52:33.203
2025-07-02 04:52:33.203 # pump out diffs from after the synch point
2025-07-02 04:52:33.203 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.203
2025-07-02 04:52:33.204 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.204 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.204
2025-07-02 04:52:33.204 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.204 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.204 alo = 364, ahi = 1101
2025-07-02 04:52:33.204 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.204 blo = 364, bhi = 1101
2025-07-02 04:52:33.204
2025-07-02 04:52:33.204 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.204 g = []
2025-07-02 04:52:33.204 if alo < ahi:
2025-07-02 04:52:33.204 if blo < bhi:
2025-07-02 04:52:33.204 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.204 else:
2025-07-02 04:52:33.204 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.204 elif blo < bhi:
2025-07-02 04:52:33.204 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.204
2025-07-02 04:52:33.204 > yield from g
2025-07-02 04:52:33.205
2025-07-02 04:52:33.205 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.205 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.205
2025-07-02 04:52:33.205 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.205 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.205 alo = 364, ahi = 1101
2025-07-02 04:52:33.205 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.205 blo = 364, bhi = 1101
2025-07-02 04:52:33.205
2025-07-02 04:52:33.205 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.205 r"""
2025-07-02 04:52:33.205 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.205 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.205 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.205 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.205
2025-07-02 04:52:33.205 Example:
2025-07-02 04:52:33.205
2025-07-02 04:52:33.206 >>> d = Differ()
2025-07-02 04:52:33.206 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.206 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.206 >>> print(''.join(results), end="")
2025-07-02 04:52:33.206 - abcDefghiJkl
2025-07-02 04:52:33.206 + abcdefGhijkl
2025-07-02 04:52:33.206 """
2025-07-02 04:52:33.206
2025-07-02 04:52:33.206 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.206 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.206 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.206 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.206 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.206
2025-07-02 04:52:33.206 # search for the pair that matches best without being identical
2025-07-02 04:52:33.206 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.206 # on junk -- unless we have to)
2025-07-02 04:52:33.207 for j in range(blo, bhi):
2025-07-02 04:52:33.207 bj = b[j]
2025-07-02 04:52:33.207 cruncher.set_seq2(bj)
2025-07-02 04:52:33.207 for i in range(alo, ahi):
2025-07-02 04:52:33.207 ai = a[i]
2025-07-02 04:52:33.207 if ai == bj:
2025-07-02 04:52:33.207 if eqi is None:
2025-07-02 04:52:33.207 eqi, eqj = i, j
2025-07-02 04:52:33.207 continue
2025-07-02 04:52:33.207 cruncher.set_seq1(ai)
2025-07-02 04:52:33.207 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.207 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.207 # compares by a factor of 3.
2025-07-02 04:52:33.207 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.207 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.207 # of the computation is cached by cruncher
2025-07-02 04:52:33.207 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.207 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.207 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.207 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.208 if best_ratio < cutoff:
2025-07-02 04:52:33.208 # no non-identical "pretty close" pair
2025-07-02 04:52:33.208 if eqi is None:
2025-07-02 04:52:33.208 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.208 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.208 return
2025-07-02 04:52:33.208 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.208 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.208 else:
2025-07-02 04:52:33.208 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.208 eqi = None
2025-07-02 04:52:33.208
2025-07-02 04:52:33.208 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.208 # identical
2025-07-02 04:52:33.208
2025-07-02 04:52:33.208 # pump out diffs from before the synch point
2025-07-02 04:52:33.208 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.208
2025-07-02 04:52:33.208 # do intraline marking on the synch pair
2025-07-02 04:52:33.208 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.208 if eqi is None:
2025-07-02 04:52:33.209 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.209 atags = btags = ""
2025-07-02 04:52:33.209 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.209 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.209 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.209 if tag == 'replace':
2025-07-02 04:52:33.209 atags += '^' * la
2025-07-02 04:52:33.209 btags += '^' * lb
2025-07-02 04:52:33.209 elif tag == 'delete':
2025-07-02 04:52:33.209 atags += '-' * la
2025-07-02 04:52:33.209 elif tag == 'insert':
2025-07-02 04:52:33.209 btags += '+' * lb
2025-07-02 04:52:33.209 elif tag == 'equal':
2025-07-02 04:52:33.209 atags += ' ' * la
2025-07-02 04:52:33.209 btags += ' ' * lb
2025-07-02 04:52:33.209 else:
2025-07-02 04:52:33.209 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.209 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.209 else:
2025-07-02 04:52:33.209 # the synch pair is identical
2025-07-02 04:52:33.209 yield ' ' + aelt
2025-07-02 04:52:33.210
2025-07-02 04:52:33.210 # pump out diffs from after the synch point
2025-07-02 04:52:33.210 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.210
2025-07-02 04:52:33.210 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.210 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.210
2025-07-02 04:52:33.210 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.210 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.210 alo = 365, ahi = 1101
2025-07-02 04:52:33.210 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.210 blo = 365, bhi = 1101
2025-07-02 04:52:33.210
2025-07-02 04:52:33.210 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.210 g = []
2025-07-02 04:52:33.210 if alo < ahi:
2025-07-02 04:52:33.210 if blo < bhi:
2025-07-02 04:52:33.210 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.210 else:
2025-07-02 04:52:33.210 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.210 elif blo < bhi:
2025-07-02 04:52:33.211 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.211
2025-07-02 04:52:33.211 > yield from g
2025-07-02 04:52:33.211
2025-07-02 04:52:33.211 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.211 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.211
2025-07-02 04:52:33.211 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.211 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.211 alo = 365, ahi = 1101
2025-07-02 04:52:33.211 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.211 blo = 365, bhi = 1101
2025-07-02 04:52:33.211
2025-07-02 04:52:33.211 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.211 r"""
2025-07-02 04:52:33.211 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.211 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.211 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.211 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.211
2025-07-02 04:52:33.211 Example:
2025-07-02 04:52:33.212
2025-07-02 04:52:33.212 >>> d = Differ()
2025-07-02 04:52:33.212 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.212 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.212 >>> print(''.join(results), end="")
2025-07-02 04:52:33.212 - abcDefghiJkl
2025-07-02 04:52:33.212 + abcdefGhijkl
2025-07-02 04:52:33.212 """
2025-07-02 04:52:33.212
2025-07-02 04:52:33.212 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.212 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.212 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.212 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.212 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.212
2025-07-02 04:52:33.212 # search for the pair that matches best without being identical
2025-07-02 04:52:33.212 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.212 # on junk -- unless we have to)
2025-07-02 04:52:33.212 for j in range(blo, bhi):
2025-07-02 04:52:33.212 bj = b[j]
2025-07-02 04:52:33.213 cruncher.set_seq2(bj)
2025-07-02 04:52:33.213 for i in range(alo, ahi):
2025-07-02 04:52:33.213 ai = a[i]
2025-07-02 04:52:33.213 if ai == bj:
2025-07-02 04:52:33.213 if eqi is None:
2025-07-02 04:52:33.213 eqi, eqj = i, j
2025-07-02 04:52:33.213 continue
2025-07-02 04:52:33.213 cruncher.set_seq1(ai)
2025-07-02 04:52:33.213 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.213 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.213 # compares by a factor of 3.
2025-07-02 04:52:33.213 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.213 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.213 # of the computation is cached by cruncher
2025-07-02 04:52:33.213 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.213 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.213 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.213 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.214 if best_ratio < cutoff:
2025-07-02 04:52:33.214 # no non-identical "pretty close" pair
2025-07-02 04:52:33.214 if eqi is None:
2025-07-02 04:52:33.214 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.214 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.214 return
2025-07-02 04:52:33.214 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.214 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.214 else:
2025-07-02 04:52:33.214 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.214 eqi = None
2025-07-02 04:52:33.214
2025-07-02 04:52:33.214 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.214 # identical
2025-07-02 04:52:33.214
2025-07-02 04:52:33.214 # pump out diffs from before the synch point
2025-07-02 04:52:33.214 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.214
2025-07-02 04:52:33.214 # do intraline marking on the synch pair
2025-07-02 04:52:33.214 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.215 if eqi is None:
2025-07-02 04:52:33.215 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.215 atags = btags = ""
2025-07-02 04:52:33.215 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.215 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.215 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.215 if tag == 'replace':
2025-07-02 04:52:33.215 atags += '^' * la
2025-07-02 04:52:33.215 btags += '^' * lb
2025-07-02 04:52:33.215 elif tag == 'delete':
2025-07-02 04:52:33.215 atags += '-' * la
2025-07-02 04:52:33.215 elif tag == 'insert':
2025-07-02 04:52:33.215 btags += '+' * lb
2025-07-02 04:52:33.215 elif tag == 'equal':
2025-07-02 04:52:33.215 atags += ' ' * la
2025-07-02 04:52:33.215 btags += ' ' * lb
2025-07-02 04:52:33.215 else:
2025-07-02 04:52:33.215 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.215 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.215 else:
2025-07-02 04:52:33.215 # the synch pair is identical
2025-07-02 04:52:33.216 yield ' ' + aelt
2025-07-02 04:52:33.216
2025-07-02 04:52:33.216 # pump out diffs from after the synch point
2025-07-02 04:52:33.216 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.216
2025-07-02 04:52:33.216 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.216 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.216
2025-07-02 04:52:33.216 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.216 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.216 alo = 366, ahi = 1101
2025-07-02 04:52:33.216 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.216 blo = 366, bhi = 1101
2025-07-02 04:52:33.216
2025-07-02 04:52:33.216 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.216 g = []
2025-07-02 04:52:33.216 if alo < ahi:
2025-07-02 04:52:33.216 if blo < bhi:
2025-07-02 04:52:33.216 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.216 else:
2025-07-02 04:52:33.216 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.217 elif blo < bhi:
2025-07-02 04:52:33.217 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.217
2025-07-02 04:52:33.217 > yield from g
2025-07-02 04:52:33.217
2025-07-02 04:52:33.217 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.217 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.217
2025-07-02 04:52:33.217 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.217 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.217 alo = 366, ahi = 1101
2025-07-02 04:52:33.217 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.217 blo = 366, bhi = 1101
2025-07-02 04:52:33.217
2025-07-02 04:52:33.217 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.217 r"""
2025-07-02 04:52:33.217 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.217 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.217 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.217 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.217
2025-07-02 04:52:33.218 Example:
2025-07-02 04:52:33.218
2025-07-02 04:52:33.218 >>> d = Differ()
2025-07-02 04:52:33.218 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.218 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.218 >>> print(''.join(results), end="")
2025-07-02 04:52:33.218 - abcDefghiJkl
2025-07-02 04:52:33.218 + abcdefGhijkl
2025-07-02 04:52:33.218 """
2025-07-02 04:52:33.218
2025-07-02 04:52:33.218 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.218 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.218 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.218 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.218 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.218
2025-07-02 04:52:33.218 # search for the pair that matches best without being identical
2025-07-02 04:52:33.218 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.218 # on junk -- unless we have to)
2025-07-02 04:52:33.218 for j in range(blo, bhi):
2025-07-02 04:52:33.219 bj = b[j]
2025-07-02 04:52:33.219 cruncher.set_seq2(bj)
2025-07-02 04:52:33.219 for i in range(alo, ahi):
2025-07-02 04:52:33.219 ai = a[i]
2025-07-02 04:52:33.219 if ai == bj:
2025-07-02 04:52:33.219 if eqi is None:
2025-07-02 04:52:33.219 eqi, eqj = i, j
2025-07-02 04:52:33.219 continue
2025-07-02 04:52:33.219 cruncher.set_seq1(ai)
2025-07-02 04:52:33.219 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.219 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.219 # compares by a factor of 3.
2025-07-02 04:52:33.219 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.219 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.219 # of the computation is cached by cruncher
2025-07-02 04:52:33.219 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.219 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.219 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.219 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.219 if best_ratio < cutoff:
2025-07-02 04:52:33.219 # no non-identical "pretty close" pair
2025-07-02 04:52:33.220 if eqi is None:
2025-07-02 04:52:33.220 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.220 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.220 return
2025-07-02 04:52:33.220 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.220 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.220 else:
2025-07-02 04:52:33.220 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.220 eqi = None
2025-07-02 04:52:33.220
2025-07-02 04:52:33.220 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.220 # identical
2025-07-02 04:52:33.220
2025-07-02 04:52:33.220 # pump out diffs from before the synch point
2025-07-02 04:52:33.220 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.220
2025-07-02 04:52:33.220 # do intraline marking on the synch pair
2025-07-02 04:52:33.220 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.220 if eqi is None:
2025-07-02 04:52:33.220 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.220 atags = btags = ""
2025-07-02 04:52:33.220 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.221 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.221 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.221 if tag == 'replace':
2025-07-02 04:52:33.221 atags += '^' * la
2025-07-02 04:52:33.221 btags += '^' * lb
2025-07-02 04:52:33.221 elif tag == 'delete':
2025-07-02 04:52:33.221 atags += '-' * la
2025-07-02 04:52:33.221 elif tag == 'insert':
2025-07-02 04:52:33.221 btags += '+' * lb
2025-07-02 04:52:33.221 elif tag == 'equal':
2025-07-02 04:52:33.221 atags += ' ' * la
2025-07-02 04:52:33.221 btags += ' ' * lb
2025-07-02 04:52:33.221 else:
2025-07-02 04:52:33.221 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.221 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.221 else:
2025-07-02 04:52:33.221 # the synch pair is identical
2025-07-02 04:52:33.221 yield ' ' + aelt
2025-07-02 04:52:33.221
2025-07-02 04:52:33.221 # pump out diffs from after the synch point
2025-07-02 04:52:33.222 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.222
2025-07-02 04:52:33.222 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.222 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.222
2025-07-02 04:52:33.222 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.222 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.222 alo = 367, ahi = 1101
2025-07-02 04:52:33.222 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.222 blo = 367, bhi = 1101
2025-07-02 04:52:33.222
2025-07-02 04:52:33.222 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.222 g = []
2025-07-02 04:52:33.222 if alo < ahi:
2025-07-02 04:52:33.222 if blo < bhi:
2025-07-02 04:52:33.222 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.222 else:
2025-07-02 04:52:33.222 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.223 elif blo < bhi:
2025-07-02 04:52:33.223 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.223
2025-07-02 04:52:33.223 > yield from g
2025-07-02 04:52:33.223
2025-07-02 04:52:33.223 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.223 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.223
2025-07-02 04:52:33.223 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.223 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.223 alo = 367, ahi = 1101
2025-07-02 04:52:33.223 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.223 blo = 367, bhi = 1101
2025-07-02 04:52:33.223
2025-07-02 04:52:33.223 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.223 r"""
2025-07-02 04:52:33.223 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.223 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.223 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.223 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.224
2025-07-02 04:52:33.224 Example:
2025-07-02 04:52:33.224
2025-07-02 04:52:33.224 >>> d = Differ()
2025-07-02 04:52:33.224 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.224 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.224 >>> print(''.join(results), end="")
2025-07-02 04:52:33.224 - abcDefghiJkl
2025-07-02 04:52:33.224 + abcdefGhijkl
2025-07-02 04:52:33.224 """
2025-07-02 04:52:33.224
2025-07-02 04:52:33.224 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.224 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.224 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.224 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.224 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.224
2025-07-02 04:52:33.224 # search for the pair that matches best without being identical
2025-07-02 04:52:33.224 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.225 # on junk -- unless we have to)
2025-07-02 04:52:33.225 for j in range(blo, bhi):
2025-07-02 04:52:33.225 bj = b[j]
2025-07-02 04:52:33.225 cruncher.set_seq2(bj)
2025-07-02 04:52:33.225 for i in range(alo, ahi):
2025-07-02 04:52:33.225 ai = a[i]
2025-07-02 04:52:33.225 if ai == bj:
2025-07-02 04:52:33.225 if eqi is None:
2025-07-02 04:52:33.225 eqi, eqj = i, j
2025-07-02 04:52:33.225 continue
2025-07-02 04:52:33.225 cruncher.set_seq1(ai)
2025-07-02 04:52:33.225 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.225 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.225 # compares by a factor of 3.
2025-07-02 04:52:33.225 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.225 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.225 # of the computation is cached by cruncher
2025-07-02 04:52:33.225 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.225 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.225 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.225 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.225 if best_ratio < cutoff:
2025-07-02 04:52:33.226 # no non-identical "pretty close" pair
2025-07-02 04:52:33.226 if eqi is None:
2025-07-02 04:52:33.226 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.226 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.226 return
2025-07-02 04:52:33.226 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.226 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.226 else:
2025-07-02 04:52:33.226 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.226 eqi = None
2025-07-02 04:52:33.226
2025-07-02 04:52:33.226 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.226 # identical
2025-07-02 04:52:33.226
2025-07-02 04:52:33.226 # pump out diffs from before the synch point
2025-07-02 04:52:33.226 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.226
2025-07-02 04:52:33.226 # do intraline marking on the synch pair
2025-07-02 04:52:33.226 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.226 if eqi is None:
2025-07-02 04:52:33.226 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.227 atags = btags = ""
2025-07-02 04:52:33.227 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.227 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.227 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.227 if tag == 'replace':
2025-07-02 04:52:33.227 atags += '^' * la
2025-07-02 04:52:33.227 btags += '^' * lb
2025-07-02 04:52:33.227 elif tag == 'delete':
2025-07-02 04:52:33.227 atags += '-' * la
2025-07-02 04:52:33.227 elif tag == 'insert':
2025-07-02 04:52:33.227 btags += '+' * lb
2025-07-02 04:52:33.227 elif tag == 'equal':
2025-07-02 04:52:33.227 atags += ' ' * la
2025-07-02 04:52:33.227 btags += ' ' * lb
2025-07-02 04:52:33.227 else:
2025-07-02 04:52:33.227 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.227 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.227 else:
2025-07-02 04:52:33.227 # the synch pair is identical
2025-07-02 04:52:33.227 yield ' ' + aelt
2025-07-02 04:52:33.227
2025-07-02 04:52:33.227 # pump out diffs from after the synch point
2025-07-02 04:52:33.228 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.228
2025-07-02 04:52:33.228 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.228 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.228
2025-07-02 04:52:33.228 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.228 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.228 alo = 368, ahi = 1101
2025-07-02 04:52:33.228 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.228 blo = 368, bhi = 1101
2025-07-02 04:52:33.228
2025-07-02 04:52:33.228 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.228 g = []
2025-07-02 04:52:33.228 if alo < ahi:
2025-07-02 04:52:33.228 if blo < bhi:
2025-07-02 04:52:33.228 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.228 else:
2025-07-02 04:52:33.228 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.228 elif blo < bhi:
2025-07-02 04:52:33.228 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.228
2025-07-02 04:52:33.229 > yield from g
2025-07-02 04:52:33.229
2025-07-02 04:52:33.229 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.229 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.229
2025-07-02 04:52:33.229 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.229 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.229 alo = 368, ahi = 1101
2025-07-02 04:52:33.229 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.229 blo = 368, bhi = 1101
2025-07-02 04:52:33.229
2025-07-02 04:52:33.229 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.229 r"""
2025-07-02 04:52:33.229 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.229 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.229 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.229 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.229
2025-07-02 04:52:33.229 Example:
2025-07-02 04:52:33.229
2025-07-02 04:52:33.229 >>> d = Differ()
2025-07-02 04:52:33.230 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.230 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.230 >>> print(''.join(results), end="")
2025-07-02 04:52:33.230 - abcDefghiJkl
2025-07-02 04:52:33.230 + abcdefGhijkl
2025-07-02 04:52:33.230 """
2025-07-02 04:52:33.230
2025-07-02 04:52:33.230 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.230 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.230 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.230 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.230 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.230
2025-07-02 04:52:33.230 # search for the pair that matches best without being identical
2025-07-02 04:52:33.230 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.230 # on junk -- unless we have to)
2025-07-02 04:52:33.230 for j in range(blo, bhi):
2025-07-02 04:52:33.230 bj = b[j]
2025-07-02 04:52:33.231 cruncher.set_seq2(bj)
2025-07-02 04:52:33.231 for i in range(alo, ahi):
2025-07-02 04:52:33.231 ai = a[i]
2025-07-02 04:52:33.231 if ai == bj:
2025-07-02 04:52:33.231 if eqi is None:
2025-07-02 04:52:33.231 eqi, eqj = i, j
2025-07-02 04:52:33.231 continue
2025-07-02 04:52:33.231 cruncher.set_seq1(ai)
2025-07-02 04:52:33.231 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.231 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.231 # compares by a factor of 3.
2025-07-02 04:52:33.231 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.231 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.231 # of the computation is cached by cruncher
2025-07-02 04:52:33.231 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.231 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.231 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.231 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.231 if best_ratio < cutoff:
2025-07-02 04:52:33.231 # no non-identical "pretty close" pair
2025-07-02 04:52:33.232 if eqi is None:
2025-07-02 04:52:33.232 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.232 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.232 return
2025-07-02 04:52:33.232 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.232 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.232 else:
2025-07-02 04:52:33.232 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.232 eqi = None
2025-07-02 04:52:33.232
2025-07-02 04:52:33.232 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.232 # identical
2025-07-02 04:52:33.232
2025-07-02 04:52:33.232 # pump out diffs from before the synch point
2025-07-02 04:52:33.232 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.232
2025-07-02 04:52:33.232 # do intraline marking on the synch pair
2025-07-02 04:52:33.232 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.232 if eqi is None:
2025-07-02 04:52:33.232 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.232 atags = btags = ""
2025-07-02 04:52:33.232 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.233 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.233 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.233 if tag == 'replace':
2025-07-02 04:52:33.233 atags += '^' * la
2025-07-02 04:52:33.233 btags += '^' * lb
2025-07-02 04:52:33.233 elif tag == 'delete':
2025-07-02 04:52:33.233 atags += '-' * la
2025-07-02 04:52:33.233 elif tag == 'insert':
2025-07-02 04:52:33.233 btags += '+' * lb
2025-07-02 04:52:33.233 elif tag == 'equal':
2025-07-02 04:52:33.233 atags += ' ' * la
2025-07-02 04:52:33.233 btags += ' ' * lb
2025-07-02 04:52:33.233 else:
2025-07-02 04:52:33.233 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.233 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.233 else:
2025-07-02 04:52:33.233 # the synch pair is identical
2025-07-02 04:52:33.233 yield ' ' + aelt
2025-07-02 04:52:33.233
2025-07-02 04:52:33.233 # pump out diffs from after the synch point
2025-07-02 04:52:33.233 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.233
2025-07-02 04:52:33.234 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.234 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.234
2025-07-02 04:52:33.234 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.234 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.234 alo = 369, ahi = 1101
2025-07-02 04:52:33.234 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.234 blo = 369, bhi = 1101
2025-07-02 04:52:33.234
2025-07-02 04:52:33.234 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.234 g = []
2025-07-02 04:52:33.234 if alo < ahi:
2025-07-02 04:52:33.234 if blo < bhi:
2025-07-02 04:52:33.234 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.234 else:
2025-07-02 04:52:33.234 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.234 elif blo < bhi:
2025-07-02 04:52:33.234 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.234
2025-07-02 04:52:33.234 > yield from g
2025-07-02 04:52:33.234
2025-07-02 04:52:33.235 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.235 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.235
2025-07-02 04:52:33.235 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.235 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.235 alo = 369, ahi = 1101
2025-07-02 04:52:33.235 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.235 blo = 369, bhi = 1101
2025-07-02 04:52:33.235
2025-07-02 04:52:33.235 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.235 r"""
2025-07-02 04:52:33.235 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.235 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.235 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.235 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.235
2025-07-02 04:52:33.235 Example:
2025-07-02 04:52:33.235
2025-07-02 04:52:33.235 >>> d = Differ()
2025-07-02 04:52:33.235 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.235 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.236 >>> print(''.join(results), end="")
2025-07-02 04:52:33.236 - abcDefghiJkl
2025-07-02 04:52:33.236 + abcdefGhijkl
2025-07-02 04:52:33.236 """
2025-07-02 04:52:33.236
2025-07-02 04:52:33.236 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.236 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.236 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.236 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.236 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.236
2025-07-02 04:52:33.236 # search for the pair that matches best without being identical
2025-07-02 04:52:33.236 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.236 # on junk -- unless we have to)
2025-07-02 04:52:33.236 for j in range(blo, bhi):
2025-07-02 04:52:33.236 bj = b[j]
2025-07-02 04:52:33.236 cruncher.set_seq2(bj)
2025-07-02 04:52:33.236 for i in range(alo, ahi):
2025-07-02 04:52:33.236 ai = a[i]
2025-07-02 04:52:33.236 if ai == bj:
2025-07-02 04:52:33.237 if eqi is None:
2025-07-02 04:52:33.237 eqi, eqj = i, j
2025-07-02 04:52:33.237 continue
2025-07-02 04:52:33.237 cruncher.set_seq1(ai)
2025-07-02 04:52:33.237 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.237 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.237 # compares by a factor of 3.
2025-07-02 04:52:33.237 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.237 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.237 # of the computation is cached by cruncher
2025-07-02 04:52:33.237 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.237 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.237 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.237 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.237 if best_ratio < cutoff:
2025-07-02 04:52:33.237 # no non-identical "pretty close" pair
2025-07-02 04:52:33.237 if eqi is None:
2025-07-02 04:52:33.237 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.237 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.237 return
2025-07-02 04:52:33.237 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.238 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.238 else:
2025-07-02 04:52:33.238 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.238 eqi = None
2025-07-02 04:52:33.238
2025-07-02 04:52:33.238 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.238 # identical
2025-07-02 04:52:33.238
2025-07-02 04:52:33.238 # pump out diffs from before the synch point
2025-07-02 04:52:33.238 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.238
2025-07-02 04:52:33.238 # do intraline marking on the synch pair
2025-07-02 04:52:33.238 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.238 if eqi is None:
2025-07-02 04:52:33.238 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.238 atags = btags = ""
2025-07-02 04:52:33.238 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.238 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.238 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.239 if tag == 'replace':
2025-07-02 04:52:33.239 atags += '^' * la
2025-07-02 04:52:33.239 btags += '^' * lb
2025-07-02 04:52:33.239 elif tag == 'delete':
2025-07-02 04:52:33.239 atags += '-' * la
2025-07-02 04:52:33.239 elif tag == 'insert':
2025-07-02 04:52:33.239 btags += '+' * lb
2025-07-02 04:52:33.239 elif tag == 'equal':
2025-07-02 04:52:33.239 atags += ' ' * la
2025-07-02 04:52:33.239 btags += ' ' * lb
2025-07-02 04:52:33.239 else:
2025-07-02 04:52:33.239 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.239 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.239 else:
2025-07-02 04:52:33.239 # the synch pair is identical
2025-07-02 04:52:33.239 yield ' ' + aelt
2025-07-02 04:52:33.239
2025-07-02 04:52:33.239 # pump out diffs from after the synch point
2025-07-02 04:52:33.239 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.239
2025-07-02 04:52:33.239 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.240 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.240
2025-07-02 04:52:33.240 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.240 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.240 alo = 370, ahi = 1101
2025-07-02 04:52:33.240 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.240 blo = 370, bhi = 1101
2025-07-02 04:52:33.240
2025-07-02 04:52:33.240 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.240 g = []
2025-07-02 04:52:33.240 if alo < ahi:
2025-07-02 04:52:33.240 if blo < bhi:
2025-07-02 04:52:33.240 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.240 else:
2025-07-02 04:52:33.240 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.240 elif blo < bhi:
2025-07-02 04:52:33.240 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.240
2025-07-02 04:52:33.240 > yield from g
2025-07-02 04:52:33.240
2025-07-02 04:52:33.240 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.241 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.241
2025-07-02 04:52:33.241 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.241 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.241 alo = 370, ahi = 1101
2025-07-02 04:52:33.241 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.241 blo = 370, bhi = 1101
2025-07-02 04:52:33.241
2025-07-02 04:52:33.241 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.241 r"""
2025-07-02 04:52:33.241 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.241 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.241 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.241 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.241
2025-07-02 04:52:33.241 Example:
2025-07-02 04:52:33.241
2025-07-02 04:52:33.241 >>> d = Differ()
2025-07-02 04:52:33.241 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.241 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.241 >>> print(''.join(results), end="")
2025-07-02 04:52:33.242 - abcDefghiJkl
2025-07-02 04:52:33.242 + abcdefGhijkl
2025-07-02 04:52:33.242 """
2025-07-02 04:52:33.242
2025-07-02 04:52:33.242 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.242 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.242 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.242 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.242 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.242
2025-07-02 04:52:33.242 # search for the pair that matches best without being identical
2025-07-02 04:52:33.242 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.242 # on junk -- unless we have to)
2025-07-02 04:52:33.242 for j in range(blo, bhi):
2025-07-02 04:52:33.242 bj = b[j]
2025-07-02 04:52:33.242 cruncher.set_seq2(bj)
2025-07-02 04:52:33.242 for i in range(alo, ahi):
2025-07-02 04:52:33.242 ai = a[i]
2025-07-02 04:52:33.243 if ai == bj:
2025-07-02 04:52:33.243 if eqi is None:
2025-07-02 04:52:33.243 eqi, eqj = i, j
2025-07-02 04:52:33.243 continue
2025-07-02 04:52:33.243 cruncher.set_seq1(ai)
2025-07-02 04:52:33.243 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.243 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.243 # compares by a factor of 3.
2025-07-02 04:52:33.243 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.243 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.243 # of the computation is cached by cruncher
2025-07-02 04:52:33.243 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.243 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.243 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.243 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.243 if best_ratio < cutoff:
2025-07-02 04:52:33.243 # no non-identical "pretty close" pair
2025-07-02 04:52:33.243 if eqi is None:
2025-07-02 04:52:33.243 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.244 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.244 return
2025-07-02 04:52:33.244 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.244 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.244 else:
2025-07-02 04:52:33.244 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.244 eqi = None
2025-07-02 04:52:33.244
2025-07-02 04:52:33.244 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.244 # identical
2025-07-02 04:52:33.244
2025-07-02 04:52:33.244 # pump out diffs from before the synch point
2025-07-02 04:52:33.244 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.244
2025-07-02 04:52:33.244 # do intraline marking on the synch pair
2025-07-02 04:52:33.244 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.244 if eqi is None:
2025-07-02 04:52:33.244 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.244 atags = btags = ""
2025-07-02 04:52:33.244 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.244 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.244 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.245 if tag == 'replace':
2025-07-02 04:52:33.245 atags += '^' * la
2025-07-02 04:52:33.245 btags += '^' * lb
2025-07-02 04:52:33.245 elif tag == 'delete':
2025-07-02 04:52:33.245 atags += '-' * la
2025-07-02 04:52:33.245 elif tag == 'insert':
2025-07-02 04:52:33.245 btags += '+' * lb
2025-07-02 04:52:33.245 elif tag == 'equal':
2025-07-02 04:52:33.245 atags += ' ' * la
2025-07-02 04:52:33.245 btags += ' ' * lb
2025-07-02 04:52:33.245 else:
2025-07-02 04:52:33.245 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.245 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.245 else:
2025-07-02 04:52:33.245 # the synch pair is identical
2025-07-02 04:52:33.245 yield ' ' + aelt
2025-07-02 04:52:33.245
2025-07-02 04:52:33.245 # pump out diffs from after the synch point
2025-07-02 04:52:33.245 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.245
2025-07-02 04:52:33.245 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.246 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.246
2025-07-02 04:52:33.246 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.246 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.246 alo = 371, ahi = 1101
2025-07-02 04:52:33.246 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.246 blo = 371, bhi = 1101
2025-07-02 04:52:33.246
2025-07-02 04:52:33.246 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.246 g = []
2025-07-02 04:52:33.246 if alo < ahi:
2025-07-02 04:52:33.246 if blo < bhi:
2025-07-02 04:52:33.246 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.246 else:
2025-07-02 04:52:33.246 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.246 elif blo < bhi:
2025-07-02 04:52:33.246 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.246
2025-07-02 04:52:33.246 > yield from g
2025-07-02 04:52:33.247
2025-07-02 04:52:33.247 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.247 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.247
2025-07-02 04:52:33.247 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.247 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.247 alo = 371, ahi = 1101
2025-07-02 04:52:33.247 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.247 blo = 371, bhi = 1101
2025-07-02 04:52:33.247
2025-07-02 04:52:33.247 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.247 r"""
2025-07-02 04:52:33.247 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.247 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.247 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.247 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.247
2025-07-02 04:52:33.247 Example:
2025-07-02 04:52:33.247
2025-07-02 04:52:33.247 >>> d = Differ()
2025-07-02 04:52:33.248 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.248 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.248 >>> print(''.join(results), end="")
2025-07-02 04:52:33.248 - abcDefghiJkl
2025-07-02 04:52:33.248 + abcdefGhijkl
2025-07-02 04:52:33.248 """
2025-07-02 04:52:33.248
2025-07-02 04:52:33.248 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.248 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.248 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.248 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.248 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.248
2025-07-02 04:52:33.248 # search for the pair that matches best without being identical
2025-07-02 04:52:33.248 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.248 # on junk -- unless we have to)
2025-07-02 04:52:33.248 for j in range(blo, bhi):
2025-07-02 04:52:33.248 bj = b[j]
2025-07-02 04:52:33.248 cruncher.set_seq2(bj)
2025-07-02 04:52:33.249 for i in range(alo, ahi):
2025-07-02 04:52:33.249 ai = a[i]
2025-07-02 04:52:33.249 if ai == bj:
2025-07-02 04:52:33.249 if eqi is None:
2025-07-02 04:52:33.249 eqi, eqj = i, j
2025-07-02 04:52:33.249 continue
2025-07-02 04:52:33.249 cruncher.set_seq1(ai)
2025-07-02 04:52:33.249 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.249 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.249 # compares by a factor of 3.
2025-07-02 04:52:33.249 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.249 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.249 # of the computation is cached by cruncher
2025-07-02 04:52:33.249 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.249 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.249 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.249 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.249 if best_ratio < cutoff:
2025-07-02 04:52:33.249 # no non-identical "pretty close" pair
2025-07-02 04:52:33.249 if eqi is None:
2025-07-02 04:52:33.249 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.249 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.250 return
2025-07-02 04:52:33.250 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.250 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.250 else:
2025-07-02 04:52:33.250 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.250 eqi = None
2025-07-02 04:52:33.250
2025-07-02 04:52:33.250 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.250 # identical
2025-07-02 04:52:33.250
2025-07-02 04:52:33.250 # pump out diffs from before the synch point
2025-07-02 04:52:33.250 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.250
2025-07-02 04:52:33.250 # do intraline marking on the synch pair
2025-07-02 04:52:33.250 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.250 if eqi is None:
2025-07-02 04:52:33.250 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.250 atags = btags = ""
2025-07-02 04:52:33.250 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.250 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.250 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.251 if tag == 'replace':
2025-07-02 04:52:33.251 atags += '^' * la
2025-07-02 04:52:33.251 btags += '^' * lb
2025-07-02 04:52:33.251 elif tag == 'delete':
2025-07-02 04:52:33.251 atags += '-' * la
2025-07-02 04:52:33.251 elif tag == 'insert':
2025-07-02 04:52:33.251 btags += '+' * lb
2025-07-02 04:52:33.251 elif tag == 'equal':
2025-07-02 04:52:33.251 atags += ' ' * la
2025-07-02 04:52:33.251 btags += ' ' * lb
2025-07-02 04:52:33.251 else:
2025-07-02 04:52:33.251 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.251 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.251 else:
2025-07-02 04:52:33.251 # the synch pair is identical
2025-07-02 04:52:33.251 yield ' ' + aelt
2025-07-02 04:52:33.251
2025-07-02 04:52:33.251 # pump out diffs from after the synch point
2025-07-02 04:52:33.251 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.251
2025-07-02 04:52:33.251 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.251 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.252
2025-07-02 04:52:33.252 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.252 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.252 alo = 372, ahi = 1101
2025-07-02 04:52:33.252 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.252 blo = 372, bhi = 1101
2025-07-02 04:52:33.252
2025-07-02 04:52:33.252 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.252 g = []
2025-07-02 04:52:33.252 if alo < ahi:
2025-07-02 04:52:33.252 if blo < bhi:
2025-07-02 04:52:33.252 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.252 else:
2025-07-02 04:52:33.252 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.252 elif blo < bhi:
2025-07-02 04:52:33.252 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.252
2025-07-02 04:52:33.252 > yield from g
2025-07-02 04:52:33.252
2025-07-02 04:52:33.252 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.252 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.253
2025-07-02 04:52:33.253 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.253 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.253 alo = 372, ahi = 1101
2025-07-02 04:52:33.253 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.253 blo = 372, bhi = 1101
2025-07-02 04:52:33.253
2025-07-02 04:52:33.253 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.253 r"""
2025-07-02 04:52:33.253 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.253 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.253 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.253 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.253
2025-07-02 04:52:33.253 Example:
2025-07-02 04:52:33.253
2025-07-02 04:52:33.253 >>> d = Differ()
2025-07-02 04:52:33.253 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.253 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.253 >>> print(''.join(results), end="")
2025-07-02 04:52:33.253 - abcDefghiJkl
2025-07-02 04:52:33.254 + abcdefGhijkl
2025-07-02 04:52:33.254 """
2025-07-02 04:52:33.254
2025-07-02 04:52:33.254 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.254 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.254 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.254 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.254 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.254
2025-07-02 04:52:33.254 # search for the pair that matches best without being identical
2025-07-02 04:52:33.254 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.254 # on junk -- unless we have to)
2025-07-02 04:52:33.254 for j in range(blo, bhi):
2025-07-02 04:52:33.254 bj = b[j]
2025-07-02 04:52:33.254 cruncher.set_seq2(bj)
2025-07-02 04:52:33.254 for i in range(alo, ahi):
2025-07-02 04:52:33.254 ai = a[i]
2025-07-02 04:52:33.254 if ai == bj:
2025-07-02 04:52:33.255 if eqi is None:
2025-07-02 04:52:33.255 eqi, eqj = i, j
2025-07-02 04:52:33.255 continue
2025-07-02 04:52:33.255 cruncher.set_seq1(ai)
2025-07-02 04:52:33.255 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.255 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.255 # compares by a factor of 3.
2025-07-02 04:52:33.255 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.255 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.255 # of the computation is cached by cruncher
2025-07-02 04:52:33.255 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.255 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.255 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.255 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.255 if best_ratio < cutoff:
2025-07-02 04:52:33.255 # no non-identical "pretty close" pair
2025-07-02 04:52:33.255 if eqi is None:
2025-07-02 04:52:33.255 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.255 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.255 return
2025-07-02 04:52:33.256 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.256 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.256 else:
2025-07-02 04:52:33.256 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.256 eqi = None
2025-07-02 04:52:33.256
2025-07-02 04:52:33.256 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.256 # identical
2025-07-02 04:52:33.256
2025-07-02 04:52:33.256 # pump out diffs from before the synch point
2025-07-02 04:52:33.256 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.256
2025-07-02 04:52:33.256 # do intraline marking on the synch pair
2025-07-02 04:52:33.256 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.256 if eqi is None:
2025-07-02 04:52:33.256 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.256 atags = btags = ""
2025-07-02 04:52:33.256 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.256 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.256 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.256 if tag == 'replace':
2025-07-02 04:52:33.257 atags += '^' * la
2025-07-02 04:52:33.257 btags += '^' * lb
2025-07-02 04:52:33.257 elif tag == 'delete':
2025-07-02 04:52:33.257 atags += '-' * la
2025-07-02 04:52:33.257 elif tag == 'insert':
2025-07-02 04:52:33.257 btags += '+' * lb
2025-07-02 04:52:33.257 elif tag == 'equal':
2025-07-02 04:52:33.257 atags += ' ' * la
2025-07-02 04:52:33.257 btags += ' ' * lb
2025-07-02 04:52:33.257 else:
2025-07-02 04:52:33.257 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.257 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.257 else:
2025-07-02 04:52:33.257 # the synch pair is identical
2025-07-02 04:52:33.257 yield ' ' + aelt
2025-07-02 04:52:33.257
2025-07-02 04:52:33.257 # pump out diffs from after the synch point
2025-07-02 04:52:33.257 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.257
2025-07-02 04:52:33.257 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.257 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.257
2025-07-02 04:52:33.258 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.258 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.258 alo = 373, ahi = 1101
2025-07-02 04:52:33.258 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.258 blo = 373, bhi = 1101
2025-07-02 04:52:33.258
2025-07-02 04:52:33.258 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.258 g = []
2025-07-02 04:52:33.258 if alo < ahi:
2025-07-02 04:52:33.258 if blo < bhi:
2025-07-02 04:52:33.258 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.258 else:
2025-07-02 04:52:33.258 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.258 elif blo < bhi:
2025-07-02 04:52:33.258 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.258
2025-07-02 04:52:33.258 > yield from g
2025-07-02 04:52:33.258
2025-07-02 04:52:33.258 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.258 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.258
2025-07-02 04:52:33.259 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.259 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.259 alo = 373, ahi = 1101
2025-07-02 04:52:33.259 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.259 blo = 373, bhi = 1101
2025-07-02 04:52:33.259
2025-07-02 04:52:33.259 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.259 r"""
2025-07-02 04:52:33.259 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.259 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.259 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.259 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.259
2025-07-02 04:52:33.259 Example:
2025-07-02 04:52:33.259
2025-07-02 04:52:33.259 >>> d = Differ()
2025-07-02 04:52:33.259 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.259 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.259 >>> print(''.join(results), end="")
2025-07-02 04:52:33.259 - abcDefghiJkl
2025-07-02 04:52:33.260 + abcdefGhijkl
2025-07-02 04:52:33.260 """
2025-07-02 04:52:33.260
2025-07-02 04:52:33.260 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.260 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.260 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.260 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.260 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.260
2025-07-02 04:52:33.260 # search for the pair that matches best without being identical
2025-07-02 04:52:33.260 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.260 # on junk -- unless we have to)
2025-07-02 04:52:33.260 for j in range(blo, bhi):
2025-07-02 04:52:33.260 bj = b[j]
2025-07-02 04:52:33.260 cruncher.set_seq2(bj)
2025-07-02 04:52:33.260 for i in range(alo, ahi):
2025-07-02 04:52:33.260 ai = a[i]
2025-07-02 04:52:33.260 if ai == bj:
2025-07-02 04:52:33.260 if eqi is None:
2025-07-02 04:52:33.260 eqi, eqj = i, j
2025-07-02 04:52:33.260 continue
2025-07-02 04:52:33.261 cruncher.set_seq1(ai)
2025-07-02 04:52:33.261 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.261 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.261 # compares by a factor of 3.
2025-07-02 04:52:33.261 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.261 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.261 # of the computation is cached by cruncher
2025-07-02 04:52:33.261 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.261 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.261 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.261 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.261 if best_ratio < cutoff:
2025-07-02 04:52:33.261 # no non-identical "pretty close" pair
2025-07-02 04:52:33.261 if eqi is None:
2025-07-02 04:52:33.261 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.261 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.261 return
2025-07-02 04:52:33.261 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.261 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.261 else:
2025-07-02 04:52:33.261 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.262 eqi = None
2025-07-02 04:52:33.262
2025-07-02 04:52:33.262 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.262 # identical
2025-07-02 04:52:33.262
2025-07-02 04:52:33.262 # pump out diffs from before the synch point
2025-07-02 04:52:33.262 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.262
2025-07-02 04:52:33.262 # do intraline marking on the synch pair
2025-07-02 04:52:33.262 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.262 if eqi is None:
2025-07-02 04:52:33.262 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.262 atags = btags = ""
2025-07-02 04:52:33.262 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.262 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.262 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.262 if tag == 'replace':
2025-07-02 04:52:33.262 atags += '^' * la
2025-07-02 04:52:33.262 btags += '^' * lb
2025-07-02 04:52:33.262 elif tag == 'delete':
2025-07-02 04:52:33.262 atags += '-' * la
2025-07-02 04:52:33.262 elif tag == 'insert':
2025-07-02 04:52:33.263 btags += '+' * lb
2025-07-02 04:52:33.263 elif tag == 'equal':
2025-07-02 04:52:33.263 atags += ' ' * la
2025-07-02 04:52:33.263 btags += ' ' * lb
2025-07-02 04:52:33.263 else:
2025-07-02 04:52:33.263 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.263 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.263 else:
2025-07-02 04:52:33.263 # the synch pair is identical
2025-07-02 04:52:33.263 yield ' ' + aelt
2025-07-02 04:52:33.263
2025-07-02 04:52:33.263 # pump out diffs from after the synch point
2025-07-02 04:52:33.263 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.263
2025-07-02 04:52:33.263 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.263 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.263
2025-07-02 04:52:33.263 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.263 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.264 alo = 374, ahi = 1101
2025-07-02 04:52:33.264 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.264 blo = 374, bhi = 1101
2025-07-02 04:52:33.264
2025-07-02 04:52:33.264 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.264 g = []
2025-07-02 04:52:33.264 if alo < ahi:
2025-07-02 04:52:33.264 if blo < bhi:
2025-07-02 04:52:33.264 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.264 else:
2025-07-02 04:52:33.264 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.264 elif blo < bhi:
2025-07-02 04:52:33.264 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.264
2025-07-02 04:52:33.264 > yield from g
2025-07-02 04:52:33.264
2025-07-02 04:52:33.264 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.264 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.264
2025-07-02 04:52:33.264 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.264 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.265 alo = 374, ahi = 1101
2025-07-02 04:52:33.265 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.265 blo = 374, bhi = 1101
2025-07-02 04:52:33.265
2025-07-02 04:52:33.265 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.265 r"""
2025-07-02 04:52:33.265 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.265 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.265 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.265 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.265
2025-07-02 04:52:33.265 Example:
2025-07-02 04:52:33.265
2025-07-02 04:52:33.265 >>> d = Differ()
2025-07-02 04:52:33.265 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.265 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.265 >>> print(''.join(results), end="")
2025-07-02 04:52:33.265 - abcDefghiJkl
2025-07-02 04:52:33.265 + abcdefGhijkl
2025-07-02 04:52:33.266 """
2025-07-02 04:52:33.266
2025-07-02 04:52:33.266 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.266 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.266 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.266 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.266 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.266
2025-07-02 04:52:33.266 # search for the pair that matches best without being identical
2025-07-02 04:52:33.266 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.266 # on junk -- unless we have to)
2025-07-02 04:52:33.266 for j in range(blo, bhi):
2025-07-02 04:52:33.266 bj = b[j]
2025-07-02 04:52:33.266 cruncher.set_seq2(bj)
2025-07-02 04:52:33.266 for i in range(alo, ahi):
2025-07-02 04:52:33.266 ai = a[i]
2025-07-02 04:52:33.266 if ai == bj:
2025-07-02 04:52:33.266 if eqi is None:
2025-07-02 04:52:33.266 eqi, eqj = i, j
2025-07-02 04:52:33.266 continue
2025-07-02 04:52:33.266 cruncher.set_seq1(ai)
2025-07-02 04:52:33.266 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.267 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.267 # compares by a factor of 3.
2025-07-02 04:52:33.267 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.267 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.267 # of the computation is cached by cruncher
2025-07-02 04:52:33.267 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.267 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.267 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.267 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.267 if best_ratio < cutoff:
2025-07-02 04:52:33.267 # no non-identical "pretty close" pair
2025-07-02 04:52:33.267 if eqi is None:
2025-07-02 04:52:33.267 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.267 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.267 return
2025-07-02 04:52:33.267 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.267 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.267 else:
2025-07-02 04:52:33.267 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.267 eqi = None
2025-07-02 04:52:33.267
2025-07-02 04:52:33.268 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.268 # identical
2025-07-02 04:52:33.268
2025-07-02 04:52:33.268 # pump out diffs from before the synch point
2025-07-02 04:52:33.268 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.268
2025-07-02 04:52:33.268 # do intraline marking on the synch pair
2025-07-02 04:52:33.268 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.268 if eqi is None:
2025-07-02 04:52:33.268 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.268 atags = btags = ""
2025-07-02 04:52:33.268 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.268 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.268 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.268 if tag == 'replace':
2025-07-02 04:52:33.268 atags += '^' * la
2025-07-02 04:52:33.268 btags += '^' * lb
2025-07-02 04:52:33.268 elif tag == 'delete':
2025-07-02 04:52:33.268 atags += '-' * la
2025-07-02 04:52:33.268 elif tag == 'insert':
2025-07-02 04:52:33.268 btags += '+' * lb
2025-07-02 04:52:33.268 elif tag == 'equal':
2025-07-02 04:52:33.269 atags += ' ' * la
2025-07-02 04:52:33.269 btags += ' ' * lb
2025-07-02 04:52:33.269 else:
2025-07-02 04:52:33.269 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.269 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.269 else:
2025-07-02 04:52:33.269 # the synch pair is identical
2025-07-02 04:52:33.269 yield ' ' + aelt
2025-07-02 04:52:33.269
2025-07-02 04:52:33.269 # pump out diffs from after the synch point
2025-07-02 04:52:33.269 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.269
2025-07-02 04:52:33.269 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.269 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.269
2025-07-02 04:52:33.269 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.269 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.269 alo = 375, ahi = 1101
2025-07-02 04:52:33.269 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.269 blo = 375, bhi = 1101
2025-07-02 04:52:33.269
2025-07-02 04:52:33.270 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.270 g = []
2025-07-02 04:52:33.270 if alo < ahi:
2025-07-02 04:52:33.270 if blo < bhi:
2025-07-02 04:52:33.270 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.270 else:
2025-07-02 04:52:33.270 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.270 elif blo < bhi:
2025-07-02 04:52:33.270 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.270
2025-07-02 04:52:33.270 > yield from g
2025-07-02 04:52:33.270
2025-07-02 04:52:33.270 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.270 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.270
2025-07-02 04:52:33.270 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.270 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.270 alo = 375, ahi = 1101
2025-07-02 04:52:33.270 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.271 blo = 375, bhi = 1101
2025-07-02 04:52:33.271
2025-07-02 04:52:33.271 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.271 r"""
2025-07-02 04:52:33.271 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.271 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.271 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.271 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.271
2025-07-02 04:52:33.271 Example:
2025-07-02 04:52:33.271
2025-07-02 04:52:33.271 >>> d = Differ()
2025-07-02 04:52:33.271 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.271 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.271 >>> print(''.join(results), end="")
2025-07-02 04:52:33.271 - abcDefghiJkl
2025-07-02 04:52:33.271 + abcdefGhijkl
2025-07-02 04:52:33.272 """
2025-07-02 04:52:33.272
2025-07-02 04:52:33.272 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.272 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.272 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.272 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.272 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.272
2025-07-02 04:52:33.272 # search for the pair that matches best without being identical
2025-07-02 04:52:33.272 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.272 # on junk -- unless we have to)
2025-07-02 04:52:33.272 for j in range(blo, bhi):
2025-07-02 04:52:33.272 bj = b[j]
2025-07-02 04:52:33.272 cruncher.set_seq2(bj)
2025-07-02 04:52:33.272 for i in range(alo, ahi):
2025-07-02 04:52:33.272 ai = a[i]
2025-07-02 04:52:33.272 if ai == bj:
2025-07-02 04:52:33.272 if eqi is None:
2025-07-02 04:52:33.272 eqi, eqj = i, j
2025-07-02 04:52:33.272 continue
2025-07-02 04:52:33.272 cruncher.set_seq1(ai)
2025-07-02 04:52:33.273 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.273 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.273 # compares by a factor of 3.
2025-07-02 04:52:33.273 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.273 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.273 # of the computation is cached by cruncher
2025-07-02 04:52:33.273 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.273 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.273 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.273 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.273 if best_ratio < cutoff:
2025-07-02 04:52:33.273 # no non-identical "pretty close" pair
2025-07-02 04:52:33.273 if eqi is None:
2025-07-02 04:52:33.273 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.273 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.273 return
2025-07-02 04:52:33.273 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.273 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.273 else:
2025-07-02 04:52:33.273 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.273 eqi = None
2025-07-02 04:52:33.274
2025-07-02 04:52:33.274 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.274 # identical
2025-07-02 04:52:33.274
2025-07-02 04:52:33.274 # pump out diffs from before the synch point
2025-07-02 04:52:33.274 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.274
2025-07-02 04:52:33.274 # do intraline marking on the synch pair
2025-07-02 04:52:33.274 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.274 if eqi is None:
2025-07-02 04:52:33.274 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.274 atags = btags = ""
2025-07-02 04:52:33.274 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.274 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.274 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.274 if tag == 'replace':
2025-07-02 04:52:33.274 atags += '^' * la
2025-07-02 04:52:33.274 btags += '^' * lb
2025-07-02 04:52:33.274 elif tag == 'delete':
2025-07-02 04:52:33.274 atags += '-' * la
2025-07-02 04:52:33.274 elif tag == 'insert':
2025-07-02 04:52:33.274 btags += '+' * lb
2025-07-02 04:52:33.275 elif tag == 'equal':
2025-07-02 04:52:33.275 atags += ' ' * la
2025-07-02 04:52:33.275 btags += ' ' * lb
2025-07-02 04:52:33.275 else:
2025-07-02 04:52:33.275 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.275 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.275 else:
2025-07-02 04:52:33.275 # the synch pair is identical
2025-07-02 04:52:33.275 yield ' ' + aelt
2025-07-02 04:52:33.275
2025-07-02 04:52:33.275 # pump out diffs from after the synch point
2025-07-02 04:52:33.275 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.275
2025-07-02 04:52:33.275 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.275 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.275
2025-07-02 04:52:33.275 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.275 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.275 alo = 378, ahi = 1101
2025-07-02 04:52:33.275 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.275 blo = 378, bhi = 1101
2025-07-02 04:52:33.276
2025-07-02 04:52:33.276 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.276 g = []
2025-07-02 04:52:33.276 if alo < ahi:
2025-07-02 04:52:33.276 if blo < bhi:
2025-07-02 04:52:33.276 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.276 else:
2025-07-02 04:52:33.276 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.276 elif blo < bhi:
2025-07-02 04:52:33.276 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.276
2025-07-02 04:52:33.276 > yield from g
2025-07-02 04:52:33.276
2025-07-02 04:52:33.276 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.276 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.276
2025-07-02 04:52:33.276 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.276 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.276 alo = 378, ahi = 1101
2025-07-02 04:52:33.276 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.276 blo = 378, bhi = 1101
2025-07-02 04:52:33.277
2025-07-02 04:52:33.277 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.277 r"""
2025-07-02 04:52:33.277 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.277 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.277 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.277 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.277
2025-07-02 04:52:33.277 Example:
2025-07-02 04:52:33.277
2025-07-02 04:52:33.277 >>> d = Differ()
2025-07-02 04:52:33.277 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.277 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.277 >>> print(''.join(results), end="")
2025-07-02 04:52:33.277 - abcDefghiJkl
2025-07-02 04:52:33.277 + abcdefGhijkl
2025-07-02 04:52:33.277 """
2025-07-02 04:52:33.277
2025-07-02 04:52:33.277 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.277 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.278 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.278 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.278 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.278
2025-07-02 04:52:33.278 # search for the pair that matches best without being identical
2025-07-02 04:52:33.278 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.278 # on junk -- unless we have to)
2025-07-02 04:52:33.278 for j in range(blo, bhi):
2025-07-02 04:52:33.278 bj = b[j]
2025-07-02 04:52:33.278 cruncher.set_seq2(bj)
2025-07-02 04:52:33.278 for i in range(alo, ahi):
2025-07-02 04:52:33.278 ai = a[i]
2025-07-02 04:52:33.278 if ai == bj:
2025-07-02 04:52:33.278 if eqi is None:
2025-07-02 04:52:33.278 eqi, eqj = i, j
2025-07-02 04:52:33.278 continue
2025-07-02 04:52:33.278 cruncher.set_seq1(ai)
2025-07-02 04:52:33.278 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.278 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.278 # compares by a factor of 3.
2025-07-02 04:52:33.278 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.278 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.279 # of the computation is cached by cruncher
2025-07-02 04:52:33.279 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.279 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.279 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.279 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.279 if best_ratio < cutoff:
2025-07-02 04:52:33.279 # no non-identical "pretty close" pair
2025-07-02 04:52:33.279 if eqi is None:
2025-07-02 04:52:33.279 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.279 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.279 return
2025-07-02 04:52:33.279 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.279 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.279 else:
2025-07-02 04:52:33.279 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.279 eqi = None
2025-07-02 04:52:33.279
2025-07-02 04:52:33.279 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.279 # identical
2025-07-02 04:52:33.279
2025-07-02 04:52:33.280 # pump out diffs from before the synch point
2025-07-02 04:52:33.280 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.280
2025-07-02 04:52:33.280 # do intraline marking on the synch pair
2025-07-02 04:52:33.280 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.280 if eqi is None:
2025-07-02 04:52:33.280 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.280 atags = btags = ""
2025-07-02 04:52:33.280 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.280 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.280 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.280 if tag == 'replace':
2025-07-02 04:52:33.280 atags += '^' * la
2025-07-02 04:52:33.280 btags += '^' * lb
2025-07-02 04:52:33.280 elif tag == 'delete':
2025-07-02 04:52:33.280 atags += '-' * la
2025-07-02 04:52:33.280 elif tag == 'insert':
2025-07-02 04:52:33.280 btags += '+' * lb
2025-07-02 04:52:33.280 elif tag == 'equal':
2025-07-02 04:52:33.280 atags += ' ' * la
2025-07-02 04:52:33.281 btags += ' ' * lb
2025-07-02 04:52:33.281 else:
2025-07-02 04:52:33.281 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.281 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.281 else:
2025-07-02 04:52:33.281 # the synch pair is identical
2025-07-02 04:52:33.281 yield ' ' + aelt
2025-07-02 04:52:33.281
2025-07-02 04:52:33.281 # pump out diffs from after the synch point
2025-07-02 04:52:33.281 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.281
2025-07-02 04:52:33.281 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.281 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.281
2025-07-02 04:52:33.281 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.281 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.281 alo = 379, ahi = 1101
2025-07-02 04:52:33.281 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.281 blo = 379, bhi = 1101
2025-07-02 04:52:33.281
2025-07-02 04:52:33.281 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.282 g = []
2025-07-02 04:52:33.282 if alo < ahi:
2025-07-02 04:52:33.282 if blo < bhi:
2025-07-02 04:52:33.282 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.282 else:
2025-07-02 04:52:33.282 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.282 elif blo < bhi:
2025-07-02 04:52:33.282 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.282
2025-07-02 04:52:33.282 > yield from g
2025-07-02 04:52:33.282
2025-07-02 04:52:33.282 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.282 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.282
2025-07-02 04:52:33.282 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.282 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.282 alo = 379, ahi = 1101
2025-07-02 04:52:33.282 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.282 blo = 379, bhi = 1101
2025-07-02 04:52:33.282
2025-07-02 04:52:33.282 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.282 r"""
2025-07-02 04:52:33.283 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.283 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.283 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.283 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.283
2025-07-02 04:52:33.283 Example:
2025-07-02 04:52:33.283
2025-07-02 04:52:33.283 >>> d = Differ()
2025-07-02 04:52:33.283 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.283 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.283 >>> print(''.join(results), end="")
2025-07-02 04:52:33.283 - abcDefghiJkl
2025-07-02 04:52:33.283 + abcdefGhijkl
2025-07-02 04:52:33.283 """
2025-07-02 04:52:33.283
2025-07-02 04:52:33.283 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.283 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.283 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.283 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.283 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.284
2025-07-02 04:52:33.284 # search for the pair that matches best without being identical
2025-07-02 04:52:33.284 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.284 # on junk -- unless we have to)
2025-07-02 04:52:33.284 for j in range(blo, bhi):
2025-07-02 04:52:33.284 bj = b[j]
2025-07-02 04:52:33.284 cruncher.set_seq2(bj)
2025-07-02 04:52:33.284 for i in range(alo, ahi):
2025-07-02 04:52:33.284 ai = a[i]
2025-07-02 04:52:33.284 if ai == bj:
2025-07-02 04:52:33.284 if eqi is None:
2025-07-02 04:52:33.284 eqi, eqj = i, j
2025-07-02 04:52:33.284 continue
2025-07-02 04:52:33.284 cruncher.set_seq1(ai)
2025-07-02 04:52:33.284 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.284 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.284 # compares by a factor of 3.
2025-07-02 04:52:33.284 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.284 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.284 # of the computation is cached by cruncher
2025-07-02 04:52:33.285 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.285 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.285 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.285 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.285 if best_ratio < cutoff:
2025-07-02 04:52:33.285 # no non-identical "pretty close" pair
2025-07-02 04:52:33.285 if eqi is None:
2025-07-02 04:52:33.285 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.285 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.285 return
2025-07-02 04:52:33.285 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.285 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.285 else:
2025-07-02 04:52:33.285 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.285 eqi = None
2025-07-02 04:52:33.285
2025-07-02 04:52:33.285 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.285 # identical
2025-07-02 04:52:33.285
2025-07-02 04:52:33.285 # pump out diffs from before the synch point
2025-07-02 04:52:33.286 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.286
2025-07-02 04:52:33.286 # do intraline marking on the synch pair
2025-07-02 04:52:33.286 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.286 if eqi is None:
2025-07-02 04:52:33.286 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.286 atags = btags = ""
2025-07-02 04:52:33.286 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.286 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.286 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.286 if tag == 'replace':
2025-07-02 04:52:33.286 atags += '^' * la
2025-07-02 04:52:33.286 btags += '^' * lb
2025-07-02 04:52:33.286 elif tag == 'delete':
2025-07-02 04:52:33.286 atags += '-' * la
2025-07-02 04:52:33.286 elif tag == 'insert':
2025-07-02 04:52:33.286 btags += '+' * lb
2025-07-02 04:52:33.286 elif tag == 'equal':
2025-07-02 04:52:33.286 atags += ' ' * la
2025-07-02 04:52:33.286 btags += ' ' * lb
2025-07-02 04:52:33.286 else:
2025-07-02 04:52:33.287 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.287 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.287 else:
2025-07-02 04:52:33.287 # the synch pair is identical
2025-07-02 04:52:33.287 yield ' ' + aelt
2025-07-02 04:52:33.287
2025-07-02 04:52:33.287 # pump out diffs from after the synch point
2025-07-02 04:52:33.287 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.287
2025-07-02 04:52:33.287 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.287 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.287
2025-07-02 04:52:33.287 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.287 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.287 alo = 380, ahi = 1101
2025-07-02 04:52:33.287 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.287 blo = 380, bhi = 1101
2025-07-02 04:52:33.287
2025-07-02 04:52:33.287 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.288 g = []
2025-07-02 04:52:33.288 if alo < ahi:
2025-07-02 04:52:33.288 if blo < bhi:
2025-07-02 04:52:33.288 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.288 else:
2025-07-02 04:52:33.288 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.288 elif blo < bhi:
2025-07-02 04:52:33.288 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.288
2025-07-02 04:52:33.288 > yield from g
2025-07-02 04:52:33.288
2025-07-02 04:52:33.288 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.288 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.288
2025-07-02 04:52:33.288 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.288 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.288 alo = 380, ahi = 1101
2025-07-02 04:52:33.288 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.288 blo = 380, bhi = 1101
2025-07-02 04:52:33.288
2025-07-02 04:52:33.289 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.289 r"""
2025-07-02 04:52:33.289 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.289 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.289 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.289 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.289
2025-07-02 04:52:33.289 Example:
2025-07-02 04:52:33.289
2025-07-02 04:52:33.289 >>> d = Differ()
2025-07-02 04:52:33.289 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.289 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.289 >>> print(''.join(results), end="")
2025-07-02 04:52:33.289 - abcDefghiJkl
2025-07-02 04:52:33.289 + abcdefGhijkl
2025-07-02 04:52:33.289 """
2025-07-02 04:52:33.289
2025-07-02 04:52:33.289 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.289 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.290 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.290 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.290 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.290
2025-07-02 04:52:33.290 # search for the pair that matches best without being identical
2025-07-02 04:52:33.290 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.290 # on junk -- unless we have to)
2025-07-02 04:52:33.290 for j in range(blo, bhi):
2025-07-02 04:52:33.290 bj = b[j]
2025-07-02 04:52:33.290 cruncher.set_seq2(bj)
2025-07-02 04:52:33.290 for i in range(alo, ahi):
2025-07-02 04:52:33.290 ai = a[i]
2025-07-02 04:52:33.290 if ai == bj:
2025-07-02 04:52:33.290 if eqi is None:
2025-07-02 04:52:33.290 eqi, eqj = i, j
2025-07-02 04:52:33.290 continue
2025-07-02 04:52:33.290 cruncher.set_seq1(ai)
2025-07-02 04:52:33.290 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.290 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.290 # compares by a factor of 3.
2025-07-02 04:52:33.290 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.291 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.291 # of the computation is cached by cruncher
2025-07-02 04:52:33.291 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.291 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.291 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.291 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.291 if best_ratio < cutoff:
2025-07-02 04:52:33.291 # no non-identical "pretty close" pair
2025-07-02 04:52:33.291 if eqi is None:
2025-07-02 04:52:33.291 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.291 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.291 return
2025-07-02 04:52:33.291 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.291 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.291 else:
2025-07-02 04:52:33.291 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.291 eqi = None
2025-07-02 04:52:33.291
2025-07-02 04:52:33.291 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.291 # identical
2025-07-02 04:52:33.291
2025-07-02 04:52:33.291 # pump out diffs from before the synch point
2025-07-02 04:52:33.292 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.292
2025-07-02 04:52:33.292 # do intraline marking on the synch pair
2025-07-02 04:52:33.292 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.292 if eqi is None:
2025-07-02 04:52:33.292 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.292 atags = btags = ""
2025-07-02 04:52:33.292 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.292 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.292 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.292 if tag == 'replace':
2025-07-02 04:52:33.292 atags += '^' * la
2025-07-02 04:52:33.292 btags += '^' * lb
2025-07-02 04:52:33.292 elif tag == 'delete':
2025-07-02 04:52:33.292 atags += '-' * la
2025-07-02 04:52:33.292 elif tag == 'insert':
2025-07-02 04:52:33.292 btags += '+' * lb
2025-07-02 04:52:33.292 elif tag == 'equal':
2025-07-02 04:52:33.292 atags += ' ' * la
2025-07-02 04:52:33.292 btags += ' ' * lb
2025-07-02 04:52:33.292 else:
2025-07-02 04:52:33.293 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.293 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.293 else:
2025-07-02 04:52:33.293 # the synch pair is identical
2025-07-02 04:52:33.293 yield ' ' + aelt
2025-07-02 04:52:33.293
2025-07-02 04:52:33.293 # pump out diffs from after the synch point
2025-07-02 04:52:33.293 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.293
2025-07-02 04:52:33.293 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.293 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.293
2025-07-02 04:52:33.293 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.293 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.293 alo = 381, ahi = 1101
2025-07-02 04:52:33.293 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.293 blo = 381, bhi = 1101
2025-07-02 04:52:33.293
2025-07-02 04:52:33.293 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.293 g = []
2025-07-02 04:52:33.294 if alo < ahi:
2025-07-02 04:52:33.294 if blo < bhi:
2025-07-02 04:52:33.294 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.294 else:
2025-07-02 04:52:33.294 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.294 elif blo < bhi:
2025-07-02 04:52:33.294 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.294
2025-07-02 04:52:33.294 > yield from g
2025-07-02 04:52:33.294
2025-07-02 04:52:33.294 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.294 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.294
2025-07-02 04:52:33.294 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.294 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.294 alo = 381, ahi = 1101
2025-07-02 04:52:33.294 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.294 blo = 381, bhi = 1101
2025-07-02 04:52:33.294
2025-07-02 04:52:33.294 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.294 r"""
2025-07-02 04:52:33.294 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.295 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.295 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.295 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.295
2025-07-02 04:52:33.295 Example:
2025-07-02 04:52:33.295
2025-07-02 04:52:33.295 >>> d = Differ()
2025-07-02 04:52:33.295 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.295 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.295 >>> print(''.join(results), end="")
2025-07-02 04:52:33.295 - abcDefghiJkl
2025-07-02 04:52:33.295 + abcdefGhijkl
2025-07-02 04:52:33.295 """
2025-07-02 04:52:33.295
2025-07-02 04:52:33.295 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.295 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.295 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.295 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.295 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.296
2025-07-02 04:52:33.296 # search for the pair that matches best without being identical
2025-07-02 04:52:33.296 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.296 # on junk -- unless we have to)
2025-07-02 04:52:33.296 for j in range(blo, bhi):
2025-07-02 04:52:33.296 bj = b[j]
2025-07-02 04:52:33.296 cruncher.set_seq2(bj)
2025-07-02 04:52:33.296 for i in range(alo, ahi):
2025-07-02 04:52:33.296 ai = a[i]
2025-07-02 04:52:33.296 if ai == bj:
2025-07-02 04:52:33.296 if eqi is None:
2025-07-02 04:52:33.296 eqi, eqj = i, j
2025-07-02 04:52:33.296 continue
2025-07-02 04:52:33.296 cruncher.set_seq1(ai)
2025-07-02 04:52:33.296 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.296 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.296 # compares by a factor of 3.
2025-07-02 04:52:33.296 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.296 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.296 # of the computation is cached by cruncher
2025-07-02 04:52:33.297 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.297 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.297 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.297 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.297 if best_ratio < cutoff:
2025-07-02 04:52:33.297 # no non-identical "pretty close" pair
2025-07-02 04:52:33.297 if eqi is None:
2025-07-02 04:52:33.297 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.297 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.297 return
2025-07-02 04:52:33.297 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.297 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.297 else:
2025-07-02 04:52:33.297 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.297 eqi = None
2025-07-02 04:52:33.297
2025-07-02 04:52:33.297 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.297 # identical
2025-07-02 04:52:33.297
2025-07-02 04:52:33.297 # pump out diffs from before the synch point
2025-07-02 04:52:33.298 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.298
2025-07-02 04:52:33.298 # do intraline marking on the synch pair
2025-07-02 04:52:33.298 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.298 if eqi is None:
2025-07-02 04:52:33.298 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.298 atags = btags = ""
2025-07-02 04:52:33.298 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.298 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.298 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.298 if tag == 'replace':
2025-07-02 04:52:33.298 atags += '^' * la
2025-07-02 04:52:33.298 btags += '^' * lb
2025-07-02 04:52:33.298 elif tag == 'delete':
2025-07-02 04:52:33.298 atags += '-' * la
2025-07-02 04:52:33.298 elif tag == 'insert':
2025-07-02 04:52:33.298 btags += '+' * lb
2025-07-02 04:52:33.298 elif tag == 'equal':
2025-07-02 04:52:33.298 atags += ' ' * la
2025-07-02 04:52:33.298 btags += ' ' * lb
2025-07-02 04:52:33.298 else:
2025-07-02 04:52:33.298 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.299 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.299 else:
2025-07-02 04:52:33.299 # the synch pair is identical
2025-07-02 04:52:33.299 yield ' ' + aelt
2025-07-02 04:52:33.299
2025-07-02 04:52:33.299 # pump out diffs from after the synch point
2025-07-02 04:52:33.299 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.299
2025-07-02 04:52:33.299 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.299 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.299
2025-07-02 04:52:33.299 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.299 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.299 alo = 382, ahi = 1101
2025-07-02 04:52:33.299 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.299 blo = 382, bhi = 1101
2025-07-02 04:52:33.299
2025-07-02 04:52:33.299 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.299 g = []
2025-07-02 04:52:33.299 if alo < ahi:
2025-07-02 04:52:33.299 if blo < bhi:
2025-07-02 04:52:33.300 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.300 else:
2025-07-02 04:52:33.300 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.300 elif blo < bhi:
2025-07-02 04:52:33.300 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.300
2025-07-02 04:52:33.300 > yield from g
2025-07-02 04:52:33.300
2025-07-02 04:52:33.300 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.300 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.300
2025-07-02 04:52:33.300 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.300 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.300 alo = 382, ahi = 1101
2025-07-02 04:52:33.300 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.300 blo = 382, bhi = 1101
2025-07-02 04:52:33.300
2025-07-02 04:52:33.300 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.300 r"""
2025-07-02 04:52:33.300 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.300 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.300 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.301 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.301
2025-07-02 04:52:33.301 Example:
2025-07-02 04:52:33.301
2025-07-02 04:52:33.301 >>> d = Differ()
2025-07-02 04:52:33.301 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.301 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.301 >>> print(''.join(results), end="")
2025-07-02 04:52:33.301 - abcDefghiJkl
2025-07-02 04:52:33.301 + abcdefGhijkl
2025-07-02 04:52:33.301 """
2025-07-02 04:52:33.301
2025-07-02 04:52:33.301 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.301 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.301 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.301 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.301 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.302
2025-07-02 04:52:33.302 # search for the pair that matches best without being identical
2025-07-02 04:52:33.302 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.302 # on junk -- unless we have to)
2025-07-02 04:52:33.302 for j in range(blo, bhi):
2025-07-02 04:52:33.302 bj = b[j]
2025-07-02 04:52:33.302 cruncher.set_seq2(bj)
2025-07-02 04:52:33.302 for i in range(alo, ahi):
2025-07-02 04:52:33.302 ai = a[i]
2025-07-02 04:52:33.302 if ai == bj:
2025-07-02 04:52:33.302 if eqi is None:
2025-07-02 04:52:33.302 eqi, eqj = i, j
2025-07-02 04:52:33.302 continue
2025-07-02 04:52:33.302 cruncher.set_seq1(ai)
2025-07-02 04:52:33.302 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.302 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.302 # compares by a factor of 3.
2025-07-02 04:52:33.302 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.302 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.302 # of the computation is cached by cruncher
2025-07-02 04:52:33.302 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.303 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.303 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.303 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.303 if best_ratio < cutoff:
2025-07-02 04:52:33.303 # no non-identical "pretty close" pair
2025-07-02 04:52:33.303 if eqi is None:
2025-07-02 04:52:33.303 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.303 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.303 return
2025-07-02 04:52:33.303 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.303 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.303 else:
2025-07-02 04:52:33.303 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.303 eqi = None
2025-07-02 04:52:33.303
2025-07-02 04:52:33.303 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.303 # identical
2025-07-02 04:52:33.303
2025-07-02 04:52:33.303 # pump out diffs from before the synch point
2025-07-02 04:52:33.303 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.303
2025-07-02 04:52:33.303 # do intraline marking on the synch pair
2025-07-02 04:52:33.304 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.304 if eqi is None:
2025-07-02 04:52:33.304 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.304 atags = btags = ""
2025-07-02 04:52:33.304 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.304 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.304 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.304 if tag == 'replace':
2025-07-02 04:52:33.304 atags += '^' * la
2025-07-02 04:52:33.304 btags += '^' * lb
2025-07-02 04:52:33.304 elif tag == 'delete':
2025-07-02 04:52:33.304 atags += '-' * la
2025-07-02 04:52:33.304 elif tag == 'insert':
2025-07-02 04:52:33.304 btags += '+' * lb
2025-07-02 04:52:33.304 elif tag == 'equal':
2025-07-02 04:52:33.304 atags += ' ' * la
2025-07-02 04:52:33.304 btags += ' ' * lb
2025-07-02 04:52:33.304 else:
2025-07-02 04:52:33.304 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.305 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.305 else:
2025-07-02 04:52:33.305 # the synch pair is identical
2025-07-02 04:52:33.305 yield ' ' + aelt
2025-07-02 04:52:33.305
2025-07-02 04:52:33.305 # pump out diffs from after the synch point
2025-07-02 04:52:33.305 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.305
2025-07-02 04:52:33.305 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.305 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.305
2025-07-02 04:52:33.305 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.305 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.305 alo = 383, ahi = 1101
2025-07-02 04:52:33.305 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.305 blo = 383, bhi = 1101
2025-07-02 04:52:33.305
2025-07-02 04:52:33.305 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.305 g = []
2025-07-02 04:52:33.305 if alo < ahi:
2025-07-02 04:52:33.306 if blo < bhi:
2025-07-02 04:52:33.306 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.306 else:
2025-07-02 04:52:33.306 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.306 elif blo < bhi:
2025-07-02 04:52:33.306 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.306
2025-07-02 04:52:33.306 > yield from g
2025-07-02 04:52:33.306
2025-07-02 04:52:33.306 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.306 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.306
2025-07-02 04:52:33.306 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.306 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.306 alo = 383, ahi = 1101
2025-07-02 04:52:33.306 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.306 blo = 383, bhi = 1101
2025-07-02 04:52:33.306
2025-07-02 04:52:33.306 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.306 r"""
2025-07-02 04:52:33.306 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.307 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.307 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.307 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.307
2025-07-02 04:52:33.307 Example:
2025-07-02 04:52:33.307
2025-07-02 04:52:33.307 >>> d = Differ()
2025-07-02 04:52:33.307 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.307 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.307 >>> print(''.join(results), end="")
2025-07-02 04:52:33.307 - abcDefghiJkl
2025-07-02 04:52:33.307 + abcdefGhijkl
2025-07-02 04:52:33.307 """
2025-07-02 04:52:33.307
2025-07-02 04:52:33.307 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.307 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.307 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.307 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.307 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.308
2025-07-02 04:52:33.308 # search for the pair that matches best without being identical
2025-07-02 04:52:33.308 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.308 # on junk -- unless we have to)
2025-07-02 04:52:33.308 for j in range(blo, bhi):
2025-07-02 04:52:33.308 bj = b[j]
2025-07-02 04:52:33.308 cruncher.set_seq2(bj)
2025-07-02 04:52:33.308 for i in range(alo, ahi):
2025-07-02 04:52:33.308 ai = a[i]
2025-07-02 04:52:33.308 if ai == bj:
2025-07-02 04:52:33.308 if eqi is None:
2025-07-02 04:52:33.308 eqi, eqj = i, j
2025-07-02 04:52:33.308 continue
2025-07-02 04:52:33.308 cruncher.set_seq1(ai)
2025-07-02 04:52:33.308 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.308 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.308 # compares by a factor of 3.
2025-07-02 04:52:33.308 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.308 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.308 # of the computation is cached by cruncher
2025-07-02 04:52:33.308 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.308 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.309 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.309 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.309 if best_ratio < cutoff:
2025-07-02 04:52:33.309 # no non-identical "pretty close" pair
2025-07-02 04:52:33.309 if eqi is None:
2025-07-02 04:52:33.309 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.309 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.309 return
2025-07-02 04:52:33.309 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.309 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.309 else:
2025-07-02 04:52:33.309 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.309 eqi = None
2025-07-02 04:52:33.309
2025-07-02 04:52:33.309 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.309 # identical
2025-07-02 04:52:33.309
2025-07-02 04:52:33.309 # pump out diffs from before the synch point
2025-07-02 04:52:33.309 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.309
2025-07-02 04:52:33.309 # do intraline marking on the synch pair
2025-07-02 04:52:33.310 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.310 if eqi is None:
2025-07-02 04:52:33.310 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.310 atags = btags = ""
2025-07-02 04:52:33.310 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.310 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.310 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.310 if tag == 'replace':
2025-07-02 04:52:33.310 atags += '^' * la
2025-07-02 04:52:33.310 btags += '^' * lb
2025-07-02 04:52:33.310 elif tag == 'delete':
2025-07-02 04:52:33.310 atags += '-' * la
2025-07-02 04:52:33.310 elif tag == 'insert':
2025-07-02 04:52:33.310 btags += '+' * lb
2025-07-02 04:52:33.310 elif tag == 'equal':
2025-07-02 04:52:33.310 atags += ' ' * la
2025-07-02 04:52:33.310 btags += ' ' * lb
2025-07-02 04:52:33.310 else:
2025-07-02 04:52:33.310 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.310 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.310 else:
2025-07-02 04:52:33.310 # the synch pair is identical
2025-07-02 04:52:33.311 yield ' ' + aelt
2025-07-02 04:52:33.311
2025-07-02 04:52:33.311 # pump out diffs from after the synch point
2025-07-02 04:52:33.311 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.311
2025-07-02 04:52:33.311 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.311 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.311
2025-07-02 04:52:33.311 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.311 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.311 alo = 384, ahi = 1101
2025-07-02 04:52:33.311 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.311 blo = 384, bhi = 1101
2025-07-02 04:52:33.311
2025-07-02 04:52:33.311 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.311 g = []
2025-07-02 04:52:33.311 if alo < ahi:
2025-07-02 04:52:33.311 if blo < bhi:
2025-07-02 04:52:33.311 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.311 else:
2025-07-02 04:52:33.311 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.312 elif blo < bhi:
2025-07-02 04:52:33.312 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.312
2025-07-02 04:52:33.312 > yield from g
2025-07-02 04:52:33.312
2025-07-02 04:52:33.312 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.312 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.312
2025-07-02 04:52:33.312 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.312 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.312 alo = 384, ahi = 1101
2025-07-02 04:52:33.312 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.312 blo = 384, bhi = 1101
2025-07-02 04:52:33.312
2025-07-02 04:52:33.312 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.312 r"""
2025-07-02 04:52:33.312 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.312 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.312 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.313 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.313
2025-07-02 04:52:33.313 Example:
2025-07-02 04:52:33.313
2025-07-02 04:52:33.313 >>> d = Differ()
2025-07-02 04:52:33.313 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.313 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.313 >>> print(''.join(results), end="")
2025-07-02 04:52:33.313 - abcDefghiJkl
2025-07-02 04:52:33.313 + abcdefGhijkl
2025-07-02 04:52:33.313 """
2025-07-02 04:52:33.313
2025-07-02 04:52:33.313 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.313 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.313 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.313 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.313 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.313
2025-07-02 04:52:33.313 # search for the pair that matches best without being identical
2025-07-02 04:52:33.314 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.314 # on junk -- unless we have to)
2025-07-02 04:52:33.314 for j in range(blo, bhi):
2025-07-02 04:52:33.314 bj = b[j]
2025-07-02 04:52:33.314 cruncher.set_seq2(bj)
2025-07-02 04:52:33.314 for i in range(alo, ahi):
2025-07-02 04:52:33.314 ai = a[i]
2025-07-02 04:52:33.314 if ai == bj:
2025-07-02 04:52:33.314 if eqi is None:
2025-07-02 04:52:33.314 eqi, eqj = i, j
2025-07-02 04:52:33.314 continue
2025-07-02 04:52:33.314 cruncher.set_seq1(ai)
2025-07-02 04:52:33.314 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.314 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.314 # compares by a factor of 3.
2025-07-02 04:52:33.314 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.314 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.314 # of the computation is cached by cruncher
2025-07-02 04:52:33.314 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.314 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.314 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.315 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.315 if best_ratio < cutoff:
2025-07-02 04:52:33.315 # no non-identical "pretty close" pair
2025-07-02 04:52:33.315 if eqi is None:
2025-07-02 04:52:33.315 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.315 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.315 return
2025-07-02 04:52:33.315 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.315 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.315 else:
2025-07-02 04:52:33.315 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.315 eqi = None
2025-07-02 04:52:33.315
2025-07-02 04:52:33.315 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.315 # identical
2025-07-02 04:52:33.315
2025-07-02 04:52:33.315 # pump out diffs from before the synch point
2025-07-02 04:52:33.315 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.315
2025-07-02 04:52:33.315 # do intraline marking on the synch pair
2025-07-02 04:52:33.315 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.315 if eqi is None:
2025-07-02 04:52:33.316 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.316 atags = btags = ""
2025-07-02 04:52:33.316 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.316 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.316 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.316 if tag == 'replace':
2025-07-02 04:52:33.316 atags += '^' * la
2025-07-02 04:52:33.316 btags += '^' * lb
2025-07-02 04:52:33.316 elif tag == 'delete':
2025-07-02 04:52:33.316 atags += '-' * la
2025-07-02 04:52:33.316 elif tag == 'insert':
2025-07-02 04:52:33.316 btags += '+' * lb
2025-07-02 04:52:33.316 elif tag == 'equal':
2025-07-02 04:52:33.316 atags += ' ' * la
2025-07-02 04:52:33.316 btags += ' ' * lb
2025-07-02 04:52:33.316 else:
2025-07-02 04:52:33.316 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.316 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.316 else:
2025-07-02 04:52:33.317 # the synch pair is identical
2025-07-02 04:52:33.317 yield ' ' + aelt
2025-07-02 04:52:33.317
2025-07-02 04:52:33.317 # pump out diffs from after the synch point
2025-07-02 04:52:33.317 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.317
2025-07-02 04:52:33.317 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.317 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.317
2025-07-02 04:52:33.317 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.317 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.317 alo = 385, ahi = 1101
2025-07-02 04:52:33.317 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.317 blo = 385, bhi = 1101
2025-07-02 04:52:33.317
2025-07-02 04:52:33.317 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.317 g = []
2025-07-02 04:52:33.317 if alo < ahi:
2025-07-02 04:52:33.317 if blo < bhi:
2025-07-02 04:52:33.317 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.318 else:
2025-07-02 04:52:33.318 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.318 elif blo < bhi:
2025-07-02 04:52:33.318 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.318
2025-07-02 04:52:33.318 > yield from g
2025-07-02 04:52:33.318
2025-07-02 04:52:33.318 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.318 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.318
2025-07-02 04:52:33.318 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.318 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.318 alo = 385, ahi = 1101
2025-07-02 04:52:33.318 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.318 blo = 385, bhi = 1101
2025-07-02 04:52:33.318
2025-07-02 04:52:33.318 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.318 r"""
2025-07-02 04:52:33.318 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.318 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.318 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.319 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.319
2025-07-02 04:52:33.319 Example:
2025-07-02 04:52:33.319
2025-07-02 04:52:33.319 >>> d = Differ()
2025-07-02 04:52:33.319 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.319 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.319 >>> print(''.join(results), end="")
2025-07-02 04:52:33.319 - abcDefghiJkl
2025-07-02 04:52:33.319 + abcdefGhijkl
2025-07-02 04:52:33.319 """
2025-07-02 04:52:33.319
2025-07-02 04:52:33.319 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.319 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.319 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.319 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.319 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.319
2025-07-02 04:52:33.319 # search for the pair that matches best without being identical
2025-07-02 04:52:33.320 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.320 # on junk -- unless we have to)
2025-07-02 04:52:33.320 for j in range(blo, bhi):
2025-07-02 04:52:33.320 bj = b[j]
2025-07-02 04:52:33.320 cruncher.set_seq2(bj)
2025-07-02 04:52:33.320 for i in range(alo, ahi):
2025-07-02 04:52:33.320 ai = a[i]
2025-07-02 04:52:33.320 if ai == bj:
2025-07-02 04:52:33.320 if eqi is None:
2025-07-02 04:52:33.320 eqi, eqj = i, j
2025-07-02 04:52:33.320 continue
2025-07-02 04:52:33.320 cruncher.set_seq1(ai)
2025-07-02 04:52:33.320 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.320 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.320 # compares by a factor of 3.
2025-07-02 04:52:33.320 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.320 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.320 # of the computation is cached by cruncher
2025-07-02 04:52:33.320 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.320 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.321 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.321 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.321 if best_ratio < cutoff:
2025-07-02 04:52:33.321 # no non-identical "pretty close" pair
2025-07-02 04:52:33.321 if eqi is None:
2025-07-02 04:52:33.321 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.321 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.321 return
2025-07-02 04:52:33.321 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.321 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.321 else:
2025-07-02 04:52:33.321 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.321 eqi = None
2025-07-02 04:52:33.321
2025-07-02 04:52:33.321 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.321 # identical
2025-07-02 04:52:33.321
2025-07-02 04:52:33.321 # pump out diffs from before the synch point
2025-07-02 04:52:33.321 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.321
2025-07-02 04:52:33.322 # do intraline marking on the synch pair
2025-07-02 04:52:33.322 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.322 if eqi is None:
2025-07-02 04:52:33.322 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.322 atags = btags = ""
2025-07-02 04:52:33.322 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.322 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.322 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.322 if tag == 'replace':
2025-07-02 04:52:33.322 atags += '^' * la
2025-07-02 04:52:33.322 btags += '^' * lb
2025-07-02 04:52:33.322 elif tag == 'delete':
2025-07-02 04:52:33.322 atags += '-' * la
2025-07-02 04:52:33.322 elif tag == 'insert':
2025-07-02 04:52:33.322 btags += '+' * lb
2025-07-02 04:52:33.322 elif tag == 'equal':
2025-07-02 04:52:33.322 atags += ' ' * la
2025-07-02 04:52:33.322 btags += ' ' * lb
2025-07-02 04:52:33.322 else:
2025-07-02 04:52:33.322 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.322 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.323 else:
2025-07-02 04:52:33.323 # the synch pair is identical
2025-07-02 04:52:33.323 yield ' ' + aelt
2025-07-02 04:52:33.323
2025-07-02 04:52:33.323 # pump out diffs from after the synch point
2025-07-02 04:52:33.323 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.323
2025-07-02 04:52:33.323 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.323 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.323
2025-07-02 04:52:33.323 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.323 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.323 alo = 386, ahi = 1101
2025-07-02 04:52:33.323 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.323 blo = 386, bhi = 1101
2025-07-02 04:52:33.323
2025-07-02 04:52:33.323 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.323 g = []
2025-07-02 04:52:33.323 if alo < ahi:
2025-07-02 04:52:33.323 if blo < bhi:
2025-07-02 04:52:33.323 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.324 else:
2025-07-02 04:52:33.324 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.324 elif blo < bhi:
2025-07-02 04:52:33.324 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.324
2025-07-02 04:52:33.324 > yield from g
2025-07-02 04:52:33.324
2025-07-02 04:52:33.324 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.324 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.324
2025-07-02 04:52:33.324 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.324 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.324 alo = 386, ahi = 1101
2025-07-02 04:52:33.324 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.324 blo = 386, bhi = 1101
2025-07-02 04:52:33.324
2025-07-02 04:52:33.324 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.324 r"""
2025-07-02 04:52:33.324 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.324 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.324 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.325 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.325
2025-07-02 04:52:33.325 Example:
2025-07-02 04:52:33.325
2025-07-02 04:52:33.325 >>> d = Differ()
2025-07-02 04:52:33.325 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.325 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.325 >>> print(''.join(results), end="")
2025-07-02 04:52:33.325 - abcDefghiJkl
2025-07-02 04:52:33.325 + abcdefGhijkl
2025-07-02 04:52:33.325 """
2025-07-02 04:52:33.325
2025-07-02 04:52:33.325 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.325 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.325 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.325 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.325 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.325
2025-07-02 04:52:33.325 # search for the pair that matches best without being identical
2025-07-02 04:52:33.325 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.326 # on junk -- unless we have to)
2025-07-02 04:52:33.326 for j in range(blo, bhi):
2025-07-02 04:52:33.326 bj = b[j]
2025-07-02 04:52:33.326 cruncher.set_seq2(bj)
2025-07-02 04:52:33.326 for i in range(alo, ahi):
2025-07-02 04:52:33.326 ai = a[i]
2025-07-02 04:52:33.326 if ai == bj:
2025-07-02 04:52:33.326 if eqi is None:
2025-07-02 04:52:33.326 eqi, eqj = i, j
2025-07-02 04:52:33.326 continue
2025-07-02 04:52:33.326 cruncher.set_seq1(ai)
2025-07-02 04:52:33.326 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.326 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.326 # compares by a factor of 3.
2025-07-02 04:52:33.326 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.326 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.326 # of the computation is cached by cruncher
2025-07-02 04:52:33.326 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.326 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.326 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.326 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.327 if best_ratio < cutoff:
2025-07-02 04:52:33.327 # no non-identical "pretty close" pair
2025-07-02 04:52:33.327 if eqi is None:
2025-07-02 04:52:33.327 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.327 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.327 return
2025-07-02 04:52:33.327 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.327 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.327 else:
2025-07-02 04:52:33.327 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.327 eqi = None
2025-07-02 04:52:33.327
2025-07-02 04:52:33.327 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.327 # identical
2025-07-02 04:52:33.327
2025-07-02 04:52:33.327 # pump out diffs from before the synch point
2025-07-02 04:52:33.327 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.327
2025-07-02 04:52:33.327 # do intraline marking on the synch pair
2025-07-02 04:52:33.327 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.327 if eqi is None:
2025-07-02 04:52:33.327 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.328 atags = btags = ""
2025-07-02 04:52:33.328 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.328 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.328 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.328 if tag == 'replace':
2025-07-02 04:52:33.328 atags += '^' * la
2025-07-02 04:52:33.328 btags += '^' * lb
2025-07-02 04:52:33.328 elif tag == 'delete':
2025-07-02 04:52:33.328 atags += '-' * la
2025-07-02 04:52:33.328 elif tag == 'insert':
2025-07-02 04:52:33.328 btags += '+' * lb
2025-07-02 04:52:33.328 elif tag == 'equal':
2025-07-02 04:52:33.328 atags += ' ' * la
2025-07-02 04:52:33.328 btags += ' ' * lb
2025-07-02 04:52:33.328 else:
2025-07-02 04:52:33.328 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.328 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.328 else:
2025-07-02 04:52:33.328 # the synch pair is identical
2025-07-02 04:52:33.328 yield ' ' + aelt
2025-07-02 04:52:33.328
2025-07-02 04:52:33.329 # pump out diffs from after the synch point
2025-07-02 04:52:33.329 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.329
2025-07-02 04:52:33.329 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.329 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.329
2025-07-02 04:52:33.329 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.329 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.329 alo = 387, ahi = 1101
2025-07-02 04:52:33.329 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.329 blo = 387, bhi = 1101
2025-07-02 04:52:33.329
2025-07-02 04:52:33.329 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.329 g = []
2025-07-02 04:52:33.329 if alo < ahi:
2025-07-02 04:52:33.329 if blo < bhi:
2025-07-02 04:52:33.329 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.329 else:
2025-07-02 04:52:33.330 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.330 elif blo < bhi:
2025-07-02 04:52:33.330 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.330
2025-07-02 04:52:33.330 > yield from g
2025-07-02 04:52:33.330
2025-07-02 04:52:33.330 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.330 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.330
2025-07-02 04:52:33.330 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.330 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.330 alo = 387, ahi = 1101
2025-07-02 04:52:33.330 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.330 blo = 387, bhi = 1101
2025-07-02 04:52:33.330
2025-07-02 04:52:33.330 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.330 r"""
2025-07-02 04:52:33.330 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.330 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.330 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.330 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.331
2025-07-02 04:52:33.331 Example:
2025-07-02 04:52:33.331
2025-07-02 04:52:33.331 >>> d = Differ()
2025-07-02 04:52:33.331 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.331 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.331 >>> print(''.join(results), end="")
2025-07-02 04:52:33.331 - abcDefghiJkl
2025-07-02 04:52:33.331 + abcdefGhijkl
2025-07-02 04:52:33.331 """
2025-07-02 04:52:33.331
2025-07-02 04:52:33.331 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.331 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.331 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.331 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.331 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.331
2025-07-02 04:52:33.331 # search for the pair that matches best without being identical
2025-07-02 04:52:33.331 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.332 # on junk -- unless we have to)
2025-07-02 04:52:33.332 for j in range(blo, bhi):
2025-07-02 04:52:33.332 bj = b[j]
2025-07-02 04:52:33.332 cruncher.set_seq2(bj)
2025-07-02 04:52:33.332 for i in range(alo, ahi):
2025-07-02 04:52:33.332 ai = a[i]
2025-07-02 04:52:33.332 if ai == bj:
2025-07-02 04:52:33.332 if eqi is None:
2025-07-02 04:52:33.332 eqi, eqj = i, j
2025-07-02 04:52:33.332 continue
2025-07-02 04:52:33.332 cruncher.set_seq1(ai)
2025-07-02 04:52:33.332 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.332 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.332 # compares by a factor of 3.
2025-07-02 04:52:33.332 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.332 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.332 # of the computation is cached by cruncher
2025-07-02 04:52:33.332 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.332 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.332 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.333 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.333 if best_ratio < cutoff:
2025-07-02 04:52:33.333 # no non-identical "pretty close" pair
2025-07-02 04:52:33.333 if eqi is None:
2025-07-02 04:52:33.333 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.333 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.333 return
2025-07-02 04:52:33.333 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.333 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.333 else:
2025-07-02 04:52:33.333 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.333 eqi = None
2025-07-02 04:52:33.333
2025-07-02 04:52:33.333 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.333 # identical
2025-07-02 04:52:33.333
2025-07-02 04:52:33.333 # pump out diffs from before the synch point
2025-07-02 04:52:33.333 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.333
2025-07-02 04:52:33.333 # do intraline marking on the synch pair
2025-07-02 04:52:33.333 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.334 if eqi is None:
2025-07-02 04:52:33.334 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.334 atags = btags = ""
2025-07-02 04:52:33.334 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.334 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.334 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.334 if tag == 'replace':
2025-07-02 04:52:33.334 atags += '^' * la
2025-07-02 04:52:33.334 btags += '^' * lb
2025-07-02 04:52:33.334 elif tag == 'delete':
2025-07-02 04:52:33.334 atags += '-' * la
2025-07-02 04:52:33.334 elif tag == 'insert':
2025-07-02 04:52:33.334 btags += '+' * lb
2025-07-02 04:52:33.334 elif tag == 'equal':
2025-07-02 04:52:33.334 atags += ' ' * la
2025-07-02 04:52:33.334 btags += ' ' * lb
2025-07-02 04:52:33.334 else:
2025-07-02 04:52:33.334 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.334 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.334 else:
2025-07-02 04:52:33.334 # the synch pair is identical
2025-07-02 04:52:33.334 yield ' ' + aelt
2025-07-02 04:52:33.335
2025-07-02 04:52:33.335 # pump out diffs from after the synch point
2025-07-02 04:52:33.335 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.335
2025-07-02 04:52:33.335 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.335 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.335
2025-07-02 04:52:33.335 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.335 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.335 alo = 388, ahi = 1101
2025-07-02 04:52:33.335 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.335 blo = 388, bhi = 1101
2025-07-02 04:52:33.335
2025-07-02 04:52:33.335 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.335 g = []
2025-07-02 04:52:33.335 if alo < ahi:
2025-07-02 04:52:33.335 if blo < bhi:
2025-07-02 04:52:33.335 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.335 else:
2025-07-02 04:52:33.335 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.335 elif blo < bhi:
2025-07-02 04:52:33.336 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.336
2025-07-02 04:52:33.336 > yield from g
2025-07-02 04:52:33.336
2025-07-02 04:52:33.336 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.336 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.336
2025-07-02 04:52:33.336 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.336 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.336 alo = 388, ahi = 1101
2025-07-02 04:52:33.336 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.336 blo = 388, bhi = 1101
2025-07-02 04:52:33.336
2025-07-02 04:52:33.336 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.336 r"""
2025-07-02 04:52:33.336 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.336 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.336 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.336 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.336
2025-07-02 04:52:33.336 Example:
2025-07-02 04:52:33.337
2025-07-02 04:52:33.337 >>> d = Differ()
2025-07-02 04:52:33.337 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.337 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.337 >>> print(''.join(results), end="")
2025-07-02 04:52:33.337 - abcDefghiJkl
2025-07-02 04:52:33.337 + abcdefGhijkl
2025-07-02 04:52:33.337 """
2025-07-02 04:52:33.337
2025-07-02 04:52:33.337 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.337 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.337 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.337 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.337 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.337
2025-07-02 04:52:33.337 # search for the pair that matches best without being identical
2025-07-02 04:52:33.337 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.338 # on junk -- unless we have to)
2025-07-02 04:52:33.338 for j in range(blo, bhi):
2025-07-02 04:52:33.338 bj = b[j]
2025-07-02 04:52:33.338 cruncher.set_seq2(bj)
2025-07-02 04:52:33.338 for i in range(alo, ahi):
2025-07-02 04:52:33.338 ai = a[i]
2025-07-02 04:52:33.338 if ai == bj:
2025-07-02 04:52:33.338 if eqi is None:
2025-07-02 04:52:33.338 eqi, eqj = i, j
2025-07-02 04:52:33.338 continue
2025-07-02 04:52:33.338 cruncher.set_seq1(ai)
2025-07-02 04:52:33.338 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.338 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.338 # compares by a factor of 3.
2025-07-02 04:52:33.338 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.338 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.338 # of the computation is cached by cruncher
2025-07-02 04:52:33.338 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.338 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.338 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.339 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.339 if best_ratio < cutoff:
2025-07-02 04:52:33.339 # no non-identical "pretty close" pair
2025-07-02 04:52:33.339 if eqi is None:
2025-07-02 04:52:33.339 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.339 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.339 return
2025-07-02 04:52:33.339 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.339 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.339 else:
2025-07-02 04:52:33.339 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.339 eqi = None
2025-07-02 04:52:33.339
2025-07-02 04:52:33.339 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.339 # identical
2025-07-02 04:52:33.339
2025-07-02 04:52:33.339 # pump out diffs from before the synch point
2025-07-02 04:52:33.339 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.339
2025-07-02 04:52:33.339 # do intraline marking on the synch pair
2025-07-02 04:52:33.339 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.340 if eqi is None:
2025-07-02 04:52:33.340 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.340 atags = btags = ""
2025-07-02 04:52:33.340 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.340 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.340 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.340 if tag == 'replace':
2025-07-02 04:52:33.340 atags += '^' * la
2025-07-02 04:52:33.340 btags += '^' * lb
2025-07-02 04:52:33.340 elif tag == 'delete':
2025-07-02 04:52:33.340 atags += '-' * la
2025-07-02 04:52:33.340 elif tag == 'insert':
2025-07-02 04:52:33.340 btags += '+' * lb
2025-07-02 04:52:33.340 elif tag == 'equal':
2025-07-02 04:52:33.340 atags += ' ' * la
2025-07-02 04:52:33.340 btags += ' ' * lb
2025-07-02 04:52:33.340 else:
2025-07-02 04:52:33.340 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.340 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.340 else:
2025-07-02 04:52:33.340 # the synch pair is identical
2025-07-02 04:52:33.340 yield ' ' + aelt
2025-07-02 04:52:33.341
2025-07-02 04:52:33.341 # pump out diffs from after the synch point
2025-07-02 04:52:33.341 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.341
2025-07-02 04:52:33.341 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.341 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.341
2025-07-02 04:52:33.341 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.341 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.341 alo = 389, ahi = 1101
2025-07-02 04:52:33.341 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.341 blo = 389, bhi = 1101
2025-07-02 04:52:33.341
2025-07-02 04:52:33.341 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.341 g = []
2025-07-02 04:52:33.341 if alo < ahi:
2025-07-02 04:52:33.341 if blo < bhi:
2025-07-02 04:52:33.341 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.341 else:
2025-07-02 04:52:33.341 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.341 elif blo < bhi:
2025-07-02 04:52:33.342 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.342
2025-07-02 04:52:33.342 > yield from g
2025-07-02 04:52:33.342
2025-07-02 04:52:33.342 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.342 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.342
2025-07-02 04:52:33.342 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.342 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.342 alo = 389, ahi = 1101
2025-07-02 04:52:33.342 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.342 blo = 389, bhi = 1101
2025-07-02 04:52:33.342
2025-07-02 04:52:33.342 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.342 r"""
2025-07-02 04:52:33.342 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.342 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.342 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.342 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.343
2025-07-02 04:52:33.343 Example:
2025-07-02 04:52:33.343
2025-07-02 04:52:33.343 >>> d = Differ()
2025-07-02 04:52:33.343 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.343 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.343 >>> print(''.join(results), end="")
2025-07-02 04:52:33.343 - abcDefghiJkl
2025-07-02 04:52:33.343 + abcdefGhijkl
2025-07-02 04:52:33.343 """
2025-07-02 04:52:33.343
2025-07-02 04:52:33.343 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.343 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.343 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.343 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.343 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.343
2025-07-02 04:52:33.343 # search for the pair that matches best without being identical
2025-07-02 04:52:33.344 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.344 # on junk -- unless we have to)
2025-07-02 04:52:33.344 for j in range(blo, bhi):
2025-07-02 04:52:33.344 bj = b[j]
2025-07-02 04:52:33.344 cruncher.set_seq2(bj)
2025-07-02 04:52:33.344 for i in range(alo, ahi):
2025-07-02 04:52:33.344 ai = a[i]
2025-07-02 04:52:33.344 if ai == bj:
2025-07-02 04:52:33.344 if eqi is None:
2025-07-02 04:52:33.344 eqi, eqj = i, j
2025-07-02 04:52:33.344 continue
2025-07-02 04:52:33.344 cruncher.set_seq1(ai)
2025-07-02 04:52:33.344 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.344 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.344 # compares by a factor of 3.
2025-07-02 04:52:33.344 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.344 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.344 # of the computation is cached by cruncher
2025-07-02 04:52:33.344 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.344 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.344 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.345 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.345 if best_ratio < cutoff:
2025-07-02 04:52:33.345 # no non-identical "pretty close" pair
2025-07-02 04:52:33.345 if eqi is None:
2025-07-02 04:52:33.345 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.345 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.345 return
2025-07-02 04:52:33.345 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.345 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.345 else:
2025-07-02 04:52:33.345 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.345 eqi = None
2025-07-02 04:52:33.345
2025-07-02 04:52:33.345 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.345 # identical
2025-07-02 04:52:33.345
2025-07-02 04:52:33.345 # pump out diffs from before the synch point
2025-07-02 04:52:33.345 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.345
2025-07-02 04:52:33.345 # do intraline marking on the synch pair
2025-07-02 04:52:33.346 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.346 if eqi is None:
2025-07-02 04:52:33.346 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.346 atags = btags = ""
2025-07-02 04:52:33.346 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.346 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.346 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.346 if tag == 'replace':
2025-07-02 04:52:33.346 atags += '^' * la
2025-07-02 04:52:33.346 btags += '^' * lb
2025-07-02 04:52:33.346 elif tag == 'delete':
2025-07-02 04:52:33.346 atags += '-' * la
2025-07-02 04:52:33.346 elif tag == 'insert':
2025-07-02 04:52:33.346 btags += '+' * lb
2025-07-02 04:52:33.346 elif tag == 'equal':
2025-07-02 04:52:33.346 atags += ' ' * la
2025-07-02 04:52:33.346 btags += ' ' * lb
2025-07-02 04:52:33.346 else:
2025-07-02 04:52:33.346 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.347 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.347 else:
2025-07-02 04:52:33.347 # the synch pair is identical
2025-07-02 04:52:33.347 yield ' ' + aelt
2025-07-02 04:52:33.347
2025-07-02 04:52:33.347 # pump out diffs from after the synch point
2025-07-02 04:52:33.347 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.347
2025-07-02 04:52:33.347 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.347 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.347
2025-07-02 04:52:33.347 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.347 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.347 alo = 390, ahi = 1101
2025-07-02 04:52:33.347 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.347 blo = 390, bhi = 1101
2025-07-02 04:52:33.347
2025-07-02 04:52:33.347 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.347 g = []
2025-07-02 04:52:33.347 if alo < ahi:
2025-07-02 04:52:33.348 if blo < bhi:
2025-07-02 04:52:33.348 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.348 else:
2025-07-02 04:52:33.348 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.348 elif blo < bhi:
2025-07-02 04:52:33.348 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.348
2025-07-02 04:52:33.348 > yield from g
2025-07-02 04:52:33.348
2025-07-02 04:52:33.348 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.348 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.348
2025-07-02 04:52:33.348 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.348 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.348 alo = 390, ahi = 1101
2025-07-02 04:52:33.348 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.348 blo = 390, bhi = 1101
2025-07-02 04:52:33.348
2025-07-02 04:52:33.349 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.349 r"""
2025-07-02 04:52:33.349 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.349 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.349 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.349 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.349
2025-07-02 04:52:33.349 Example:
2025-07-02 04:52:33.349
2025-07-02 04:52:33.349 >>> d = Differ()
2025-07-02 04:52:33.349 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.349 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.349 >>> print(''.join(results), end="")
2025-07-02 04:52:33.349 - abcDefghiJkl
2025-07-02 04:52:33.349 + abcdefGhijkl
2025-07-02 04:52:33.349 """
2025-07-02 04:52:33.349
2025-07-02 04:52:33.349 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.350 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.350 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.350 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.350 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.350
2025-07-02 04:52:33.350 # search for the pair that matches best without being identical
2025-07-02 04:52:33.350 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.350 # on junk -- unless we have to)
2025-07-02 04:52:33.350 for j in range(blo, bhi):
2025-07-02 04:52:33.350 bj = b[j]
2025-07-02 04:52:33.350 cruncher.set_seq2(bj)
2025-07-02 04:52:33.350 for i in range(alo, ahi):
2025-07-02 04:52:33.350 ai = a[i]
2025-07-02 04:52:33.350 if ai == bj:
2025-07-02 04:52:33.350 if eqi is None:
2025-07-02 04:52:33.350 eqi, eqj = i, j
2025-07-02 04:52:33.350 continue
2025-07-02 04:52:33.350 cruncher.set_seq1(ai)
2025-07-02 04:52:33.350 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.350 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.350 # compares by a factor of 3.
2025-07-02 04:52:33.351 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.351 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.351 # of the computation is cached by cruncher
2025-07-02 04:52:33.351 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.351 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.351 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.351 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.351 if best_ratio < cutoff:
2025-07-02 04:52:33.351 # no non-identical "pretty close" pair
2025-07-02 04:52:33.351 if eqi is None:
2025-07-02 04:52:33.351 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.351 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.351 return
2025-07-02 04:52:33.351 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.351 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.351 else:
2025-07-02 04:52:33.351 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.351 eqi = None
2025-07-02 04:52:33.351
2025-07-02 04:52:33.351 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.352 # identical
2025-07-02 04:52:33.352
2025-07-02 04:52:33.352 # pump out diffs from before the synch point
2025-07-02 04:52:33.352 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.352
2025-07-02 04:52:33.352 # do intraline marking on the synch pair
2025-07-02 04:52:33.352 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.352 if eqi is None:
2025-07-02 04:52:33.352 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.352 atags = btags = ""
2025-07-02 04:52:33.352 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.352 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.352 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.352 if tag == 'replace':
2025-07-02 04:52:33.352 atags += '^' * la
2025-07-02 04:52:33.352 btags += '^' * lb
2025-07-02 04:52:33.352 elif tag == 'delete':
2025-07-02 04:52:33.352 atags += '-' * la
2025-07-02 04:52:33.352 elif tag == 'insert':
2025-07-02 04:52:33.352 btags += '+' * lb
2025-07-02 04:52:33.352 elif tag == 'equal':
2025-07-02 04:52:33.353 atags += ' ' * la
2025-07-02 04:52:33.353 btags += ' ' * lb
2025-07-02 04:52:33.353 else:
2025-07-02 04:52:33.353 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.353 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.353 else:
2025-07-02 04:52:33.353 # the synch pair is identical
2025-07-02 04:52:33.353 yield ' ' + aelt
2025-07-02 04:52:33.353
2025-07-02 04:52:33.353 # pump out diffs from after the synch point
2025-07-02 04:52:33.353 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.353
2025-07-02 04:52:33.353 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.353 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.353
2025-07-02 04:52:33.353 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.353 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.353 alo = 391, ahi = 1101
2025-07-02 04:52:33.353 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.353 blo = 391, bhi = 1101
2025-07-02 04:52:33.353
2025-07-02 04:52:33.354 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.354 g = []
2025-07-02 04:52:33.354 if alo < ahi:
2025-07-02 04:52:33.354 if blo < bhi:
2025-07-02 04:52:33.354 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.354 else:
2025-07-02 04:52:33.354 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.354 elif blo < bhi:
2025-07-02 04:52:33.354 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.354
2025-07-02 04:52:33.354 > yield from g
2025-07-02 04:52:33.354
2025-07-02 04:52:33.354 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.354 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.354
2025-07-02 04:52:33.354 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.354 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.354 alo = 391, ahi = 1101
2025-07-02 04:52:33.355 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.355 blo = 391, bhi = 1101
2025-07-02 04:52:33.355
2025-07-02 04:52:33.355 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.355 r"""
2025-07-02 04:52:33.355 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.355 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.355 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.355 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.355
2025-07-02 04:52:33.355 Example:
2025-07-02 04:52:33.355
2025-07-02 04:52:33.355 >>> d = Differ()
2025-07-02 04:52:33.355 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.355 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.355 >>> print(''.join(results), end="")
2025-07-02 04:52:33.355 - abcDefghiJkl
2025-07-02 04:52:33.355 + abcdefGhijkl
2025-07-02 04:52:33.356 """
2025-07-02 04:52:33.356
2025-07-02 04:52:33.356 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.356 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.356 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.356 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.356 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.356
2025-07-02 04:52:33.356 # search for the pair that matches best without being identical
2025-07-02 04:52:33.356 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.356 # on junk -- unless we have to)
2025-07-02 04:52:33.356 for j in range(blo, bhi):
2025-07-02 04:52:33.356 bj = b[j]
2025-07-02 04:52:33.356 cruncher.set_seq2(bj)
2025-07-02 04:52:33.356 for i in range(alo, ahi):
2025-07-02 04:52:33.356 ai = a[i]
2025-07-02 04:52:33.356 if ai == bj:
2025-07-02 04:52:33.356 if eqi is None:
2025-07-02 04:52:33.356 eqi, eqj = i, j
2025-07-02 04:52:33.356 continue
2025-07-02 04:52:33.356 cruncher.set_seq1(ai)
2025-07-02 04:52:33.357 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.357 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.357 # compares by a factor of 3.
2025-07-02 04:52:33.357 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.357 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.357 # of the computation is cached by cruncher
2025-07-02 04:52:33.357 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.357 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.357 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.357 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.357 if best_ratio < cutoff:
2025-07-02 04:52:33.357 # no non-identical "pretty close" pair
2025-07-02 04:52:33.357 if eqi is None:
2025-07-02 04:52:33.357 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.357 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.357 return
2025-07-02 04:52:33.357 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.357 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.357 else:
2025-07-02 04:52:33.357 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.358 eqi = None
2025-07-02 04:52:33.358
2025-07-02 04:52:33.358 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.358 # identical
2025-07-02 04:52:33.358
2025-07-02 04:52:33.358 # pump out diffs from before the synch point
2025-07-02 04:52:33.358 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.358
2025-07-02 04:52:33.358 # do intraline marking on the synch pair
2025-07-02 04:52:33.358 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.358 if eqi is None:
2025-07-02 04:52:33.358 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.358 atags = btags = ""
2025-07-02 04:52:33.358 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.358 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.358 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.358 if tag == 'replace':
2025-07-02 04:52:33.358 atags += '^' * la
2025-07-02 04:52:33.358 btags += '^' * lb
2025-07-02 04:52:33.358 elif tag == 'delete':
2025-07-02 04:52:33.358 atags += '-' * la
2025-07-02 04:52:33.359 elif tag == 'insert':
2025-07-02 04:52:33.359 btags += '+' * lb
2025-07-02 04:52:33.359 elif tag == 'equal':
2025-07-02 04:52:33.359 atags += ' ' * la
2025-07-02 04:52:33.359 btags += ' ' * lb
2025-07-02 04:52:33.359 else:
2025-07-02 04:52:33.359 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.359 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.359 else:
2025-07-02 04:52:33.359 # the synch pair is identical
2025-07-02 04:52:33.359 yield ' ' + aelt
2025-07-02 04:52:33.359
2025-07-02 04:52:33.359 # pump out diffs from after the synch point
2025-07-02 04:52:33.359 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.359
2025-07-02 04:52:33.359 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.359 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.359
2025-07-02 04:52:33.359 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.359 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.360 alo = 392, ahi = 1101
2025-07-02 04:52:33.360 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.360 blo = 392, bhi = 1101
2025-07-02 04:52:33.360
2025-07-02 04:52:33.360 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.360 g = []
2025-07-02 04:52:33.360 if alo < ahi:
2025-07-02 04:52:33.360 if blo < bhi:
2025-07-02 04:52:33.360 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.360 else:
2025-07-02 04:52:33.360 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.360 elif blo < bhi:
2025-07-02 04:52:33.360 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.360
2025-07-02 04:52:33.360 > yield from g
2025-07-02 04:52:33.360
2025-07-02 04:52:33.360 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.360 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.360
2025-07-02 04:52:33.360 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.360 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.361 alo = 392, ahi = 1101
2025-07-02 04:52:33.361 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.361 blo = 392, bhi = 1101
2025-07-02 04:52:33.361
2025-07-02 04:52:33.361 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.361 r"""
2025-07-02 04:52:33.361 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.361 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.361 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.361 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.361
2025-07-02 04:52:33.361 Example:
2025-07-02 04:52:33.361
2025-07-02 04:52:33.361 >>> d = Differ()
2025-07-02 04:52:33.361 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.361 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.361 >>> print(''.join(results), end="")
2025-07-02 04:52:33.361 - abcDefghiJkl
2025-07-02 04:52:33.361 + abcdefGhijkl
2025-07-02 04:52:33.362 """
2025-07-02 04:52:33.362
2025-07-02 04:52:33.362 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.362 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.362 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.362 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.362 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.362
2025-07-02 04:52:33.362 # search for the pair that matches best without being identical
2025-07-02 04:52:33.362 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.362 # on junk -- unless we have to)
2025-07-02 04:52:33.362 for j in range(blo, bhi):
2025-07-02 04:52:33.362 bj = b[j]
2025-07-02 04:52:33.362 cruncher.set_seq2(bj)
2025-07-02 04:52:33.362 for i in range(alo, ahi):
2025-07-02 04:52:33.362 ai = a[i]
2025-07-02 04:52:33.362 if ai == bj:
2025-07-02 04:52:33.362 if eqi is None:
2025-07-02 04:52:33.362 eqi, eqj = i, j
2025-07-02 04:52:33.363 continue
2025-07-02 04:52:33.363 cruncher.set_seq1(ai)
2025-07-02 04:52:33.363 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.363 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.363 # compares by a factor of 3.
2025-07-02 04:52:33.363 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.363 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.363 # of the computation is cached by cruncher
2025-07-02 04:52:33.363 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.363 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.363 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.363 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.363 if best_ratio < cutoff:
2025-07-02 04:52:33.363 # no non-identical "pretty close" pair
2025-07-02 04:52:33.363 if eqi is None:
2025-07-02 04:52:33.363 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.363 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.363 return
2025-07-02 04:52:33.363 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.363 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.364 else:
2025-07-02 04:52:33.364 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.364 eqi = None
2025-07-02 04:52:33.364
2025-07-02 04:52:33.364 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.364 # identical
2025-07-02 04:52:33.364
2025-07-02 04:52:33.364 # pump out diffs from before the synch point
2025-07-02 04:52:33.364 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.364
2025-07-02 04:52:33.364 # do intraline marking on the synch pair
2025-07-02 04:52:33.364 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.364 if eqi is None:
2025-07-02 04:52:33.364 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.364 atags = btags = ""
2025-07-02 04:52:33.364 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.364 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.364 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.364 if tag == 'replace':
2025-07-02 04:52:33.364 atags += '^' * la
2025-07-02 04:52:33.365 btags += '^' * lb
2025-07-02 04:52:33.365 elif tag == 'delete':
2025-07-02 04:52:33.365 atags += '-' * la
2025-07-02 04:52:33.365 elif tag == 'insert':
2025-07-02 04:52:33.365 btags += '+' * lb
2025-07-02 04:52:33.365 elif tag == 'equal':
2025-07-02 04:52:33.365 atags += ' ' * la
2025-07-02 04:52:33.365 btags += ' ' * lb
2025-07-02 04:52:33.365 else:
2025-07-02 04:52:33.365 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.365 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.365 else:
2025-07-02 04:52:33.365 # the synch pair is identical
2025-07-02 04:52:33.365 yield ' ' + aelt
2025-07-02 04:52:33.365
2025-07-02 04:52:33.365 # pump out diffs from after the synch point
2025-07-02 04:52:33.365 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.365
2025-07-02 04:52:33.365 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.365 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.365
2025-07-02 04:52:33.366 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.366 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.366 alo = 393, ahi = 1101
2025-07-02 04:52:33.366 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.366 blo = 393, bhi = 1101
2025-07-02 04:52:33.366
2025-07-02 04:52:33.366 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.366 g = []
2025-07-02 04:52:33.366 if alo < ahi:
2025-07-02 04:52:33.366 if blo < bhi:
2025-07-02 04:52:33.366 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.366 else:
2025-07-02 04:52:33.366 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.366 elif blo < bhi:
2025-07-02 04:52:33.366 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.366
2025-07-02 04:52:33.366 > yield from g
2025-07-02 04:52:33.366
2025-07-02 04:52:33.366 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.366 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.366
2025-07-02 04:52:33.367 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.367 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.367 alo = 393, ahi = 1101
2025-07-02 04:52:33.367 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.367 blo = 393, bhi = 1101
2025-07-02 04:52:33.367
2025-07-02 04:52:33.367 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.367 r"""
2025-07-02 04:52:33.367 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.367 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.367 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.367 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.367
2025-07-02 04:52:33.367 Example:
2025-07-02 04:52:33.367
2025-07-02 04:52:33.367 >>> d = Differ()
2025-07-02 04:52:33.367 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.367 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.367 >>> print(''.join(results), end="")
2025-07-02 04:52:33.367 - abcDefghiJkl
2025-07-02 04:52:33.368 + abcdefGhijkl
2025-07-02 04:52:33.368 """
2025-07-02 04:52:33.368
2025-07-02 04:52:33.368 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.368 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.368 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.368 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.368 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.368
2025-07-02 04:52:33.368 # search for the pair that matches best without being identical
2025-07-02 04:52:33.368 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.368 # on junk -- unless we have to)
2025-07-02 04:52:33.368 for j in range(blo, bhi):
2025-07-02 04:52:33.368 bj = b[j]
2025-07-02 04:52:33.368 cruncher.set_seq2(bj)
2025-07-02 04:52:33.368 for i in range(alo, ahi):
2025-07-02 04:52:33.368 ai = a[i]
2025-07-02 04:52:33.368 if ai == bj:
2025-07-02 04:52:33.368 if eqi is None:
2025-07-02 04:52:33.368 eqi, eqj = i, j
2025-07-02 04:52:33.368 continue
2025-07-02 04:52:33.369 cruncher.set_seq1(ai)
2025-07-02 04:52:33.369 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.369 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.369 # compares by a factor of 3.
2025-07-02 04:52:33.369 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.369 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.369 # of the computation is cached by cruncher
2025-07-02 04:52:33.369 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.369 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.369 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.369 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.369 if best_ratio < cutoff:
2025-07-02 04:52:33.369 # no non-identical "pretty close" pair
2025-07-02 04:52:33.369 if eqi is None:
2025-07-02 04:52:33.369 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.369 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.369 return
2025-07-02 04:52:33.369 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.369 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.369 else:
2025-07-02 04:52:33.369 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.370 eqi = None
2025-07-02 04:52:33.370
2025-07-02 04:52:33.370 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.370 # identical
2025-07-02 04:52:33.370
2025-07-02 04:52:33.370 # pump out diffs from before the synch point
2025-07-02 04:52:33.370 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.370
2025-07-02 04:52:33.370 # do intraline marking on the synch pair
2025-07-02 04:52:33.370 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.370 if eqi is None:
2025-07-02 04:52:33.370 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.370 atags = btags = ""
2025-07-02 04:52:33.370 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.370 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.370 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.370 if tag == 'replace':
2025-07-02 04:52:33.370 atags += '^' * la
2025-07-02 04:52:33.370 btags += '^' * lb
2025-07-02 04:52:33.370 elif tag == 'delete':
2025-07-02 04:52:33.370 atags += '-' * la
2025-07-02 04:52:33.370 elif tag == 'insert':
2025-07-02 04:52:33.371 btags += '+' * lb
2025-07-02 04:52:33.371 elif tag == 'equal':
2025-07-02 04:52:33.371 atags += ' ' * la
2025-07-02 04:52:33.371 btags += ' ' * lb
2025-07-02 04:52:33.371 else:
2025-07-02 04:52:33.371 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.371 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.371 else:
2025-07-02 04:52:33.371 # the synch pair is identical
2025-07-02 04:52:33.371 yield ' ' + aelt
2025-07-02 04:52:33.371
2025-07-02 04:52:33.371 # pump out diffs from after the synch point
2025-07-02 04:52:33.371 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.371
2025-07-02 04:52:33.371 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.371 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.371
2025-07-02 04:52:33.371 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.371 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.372 alo = 394, ahi = 1101
2025-07-02 04:52:33.372 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.372 blo = 394, bhi = 1101
2025-07-02 04:52:33.372
2025-07-02 04:52:33.372 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.372 g = []
2025-07-02 04:52:33.372 if alo < ahi:
2025-07-02 04:52:33.372 if blo < bhi:
2025-07-02 04:52:33.372 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.372 else:
2025-07-02 04:52:33.372 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.372 elif blo < bhi:
2025-07-02 04:52:33.372 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.372
2025-07-02 04:52:33.372 > yield from g
2025-07-02 04:52:33.372
2025-07-02 04:52:33.372 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.372 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.372
2025-07-02 04:52:33.372 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.373 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.373 alo = 394, ahi = 1101
2025-07-02 04:52:33.373 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.373 blo = 394, bhi = 1101
2025-07-02 04:52:33.373
2025-07-02 04:52:33.373 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.373 r"""
2025-07-02 04:52:33.373 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.373 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.373 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.373 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.373
2025-07-02 04:52:33.373 Example:
2025-07-02 04:52:33.373
2025-07-02 04:52:33.373 >>> d = Differ()
2025-07-02 04:52:33.373 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.373 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.373 >>> print(''.join(results), end="")
2025-07-02 04:52:33.373 - abcDefghiJkl
2025-07-02 04:52:33.373 + abcdefGhijkl
2025-07-02 04:52:33.374 """
2025-07-02 04:52:33.374
2025-07-02 04:52:33.374 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.374 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.374 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.374 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.374 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.374
2025-07-02 04:52:33.374 # search for the pair that matches best without being identical
2025-07-02 04:52:33.374 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.374 # on junk -- unless we have to)
2025-07-02 04:52:33.374 for j in range(blo, bhi):
2025-07-02 04:52:33.374 bj = b[j]
2025-07-02 04:52:33.374 cruncher.set_seq2(bj)
2025-07-02 04:52:33.374 for i in range(alo, ahi):
2025-07-02 04:52:33.374 ai = a[i]
2025-07-02 04:52:33.374 if ai == bj:
2025-07-02 04:52:33.374 if eqi is None:
2025-07-02 04:52:33.374 eqi, eqj = i, j
2025-07-02 04:52:33.374 continue
2025-07-02 04:52:33.374 cruncher.set_seq1(ai)
2025-07-02 04:52:33.375 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.375 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.375 # compares by a factor of 3.
2025-07-02 04:52:33.375 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.375 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.375 # of the computation is cached by cruncher
2025-07-02 04:52:33.375 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.375 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.375 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.375 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.375 if best_ratio < cutoff:
2025-07-02 04:52:33.375 # no non-identical "pretty close" pair
2025-07-02 04:52:33.375 if eqi is None:
2025-07-02 04:52:33.375 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.375 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.375 return
2025-07-02 04:52:33.375 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.375 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.375 else:
2025-07-02 04:52:33.375 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.375 eqi = None
2025-07-02 04:52:33.376
2025-07-02 04:52:33.376 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.376 # identical
2025-07-02 04:52:33.376
2025-07-02 04:52:33.376 # pump out diffs from before the synch point
2025-07-02 04:52:33.376 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.376
2025-07-02 04:52:33.376 # do intraline marking on the synch pair
2025-07-02 04:52:33.376 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.376 if eqi is None:
2025-07-02 04:52:33.376 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.376 atags = btags = ""
2025-07-02 04:52:33.376 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.376 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.376 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.376 if tag == 'replace':
2025-07-02 04:52:33.376 atags += '^' * la
2025-07-02 04:52:33.376 btags += '^' * lb
2025-07-02 04:52:33.376 elif tag == 'delete':
2025-07-02 04:52:33.376 atags += '-' * la
2025-07-02 04:52:33.376 elif tag == 'insert':
2025-07-02 04:52:33.377 btags += '+' * lb
2025-07-02 04:52:33.377 elif tag == 'equal':
2025-07-02 04:52:33.377 atags += ' ' * la
2025-07-02 04:52:33.377 btags += ' ' * lb
2025-07-02 04:52:33.377 else:
2025-07-02 04:52:33.377 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.377 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.377 else:
2025-07-02 04:52:33.377 # the synch pair is identical
2025-07-02 04:52:33.377 yield ' ' + aelt
2025-07-02 04:52:33.377
2025-07-02 04:52:33.377 # pump out diffs from after the synch point
2025-07-02 04:52:33.377 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.377
2025-07-02 04:52:33.377 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.377 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.377
2025-07-02 04:52:33.377 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.377 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.377 alo = 395, ahi = 1101
2025-07-02 04:52:33.377 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.377 blo = 395, bhi = 1101
2025-07-02 04:52:33.378
2025-07-02 04:52:33.378 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.378 g = []
2025-07-02 04:52:33.378 if alo < ahi:
2025-07-02 04:52:33.378 if blo < bhi:
2025-07-02 04:52:33.378 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.378 else:
2025-07-02 04:52:33.378 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.378 elif blo < bhi:
2025-07-02 04:52:33.378 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.378
2025-07-02 04:52:33.378 > yield from g
2025-07-02 04:52:33.378
2025-07-02 04:52:33.378 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.378 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.378
2025-07-02 04:52:33.378 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.378 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.378 alo = 395, ahi = 1101
2025-07-02 04:52:33.378 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.378 blo = 395, bhi = 1101
2025-07-02 04:52:33.379
2025-07-02 04:52:33.379 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.379 r"""
2025-07-02 04:52:33.379 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.379 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.379 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.379 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.379
2025-07-02 04:52:33.379 Example:
2025-07-02 04:52:33.379
2025-07-02 04:52:33.379 >>> d = Differ()
2025-07-02 04:52:33.379 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.379 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.379 >>> print(''.join(results), end="")
2025-07-02 04:52:33.379 - abcDefghiJkl
2025-07-02 04:52:33.379 + abcdefGhijkl
2025-07-02 04:52:33.379 """
2025-07-02 04:52:33.379
2025-07-02 04:52:33.380 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.380 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.380 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.380 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.380 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.380
2025-07-02 04:52:33.380 # search for the pair that matches best without being identical
2025-07-02 04:52:33.380 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.380 # on junk -- unless we have to)
2025-07-02 04:52:33.380 for j in range(blo, bhi):
2025-07-02 04:52:33.380 bj = b[j]
2025-07-02 04:52:33.380 cruncher.set_seq2(bj)
2025-07-02 04:52:33.380 for i in range(alo, ahi):
2025-07-02 04:52:33.380 ai = a[i]
2025-07-02 04:52:33.380 if ai == bj:
2025-07-02 04:52:33.380 if eqi is None:
2025-07-02 04:52:33.380 eqi, eqj = i, j
2025-07-02 04:52:33.380 continue
2025-07-02 04:52:33.380 cruncher.set_seq1(ai)
2025-07-02 04:52:33.380 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.380 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.381 # compares by a factor of 3.
2025-07-02 04:52:33.381 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.381 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.381 # of the computation is cached by cruncher
2025-07-02 04:52:33.381 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.381 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.381 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.381 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.381 if best_ratio < cutoff:
2025-07-02 04:52:33.381 # no non-identical "pretty close" pair
2025-07-02 04:52:33.381 if eqi is None:
2025-07-02 04:52:33.381 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.381 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.381 return
2025-07-02 04:52:33.381 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.381 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.381 else:
2025-07-02 04:52:33.381 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.381 eqi = None
2025-07-02 04:52:33.381
2025-07-02 04:52:33.382 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.382 # identical
2025-07-02 04:52:33.382
2025-07-02 04:52:33.382 # pump out diffs from before the synch point
2025-07-02 04:52:33.382 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.382
2025-07-02 04:52:33.382 # do intraline marking on the synch pair
2025-07-02 04:52:33.382 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.382 if eqi is None:
2025-07-02 04:52:33.382 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.382 atags = btags = ""
2025-07-02 04:52:33.382 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.382 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.382 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.382 if tag == 'replace':
2025-07-02 04:52:33.382 atags += '^' * la
2025-07-02 04:52:33.382 btags += '^' * lb
2025-07-02 04:52:33.382 elif tag == 'delete':
2025-07-02 04:52:33.382 atags += '-' * la
2025-07-02 04:52:33.382 elif tag == 'insert':
2025-07-02 04:52:33.382 btags += '+' * lb
2025-07-02 04:52:33.383 elif tag == 'equal':
2025-07-02 04:52:33.383 atags += ' ' * la
2025-07-02 04:52:33.383 btags += ' ' * lb
2025-07-02 04:52:33.383 else:
2025-07-02 04:52:33.383 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.383 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.383 else:
2025-07-02 04:52:33.383 # the synch pair is identical
2025-07-02 04:52:33.383 yield ' ' + aelt
2025-07-02 04:52:33.383
2025-07-02 04:52:33.383 # pump out diffs from after the synch point
2025-07-02 04:52:33.383 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.383
2025-07-02 04:52:33.383 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.383 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.383
2025-07-02 04:52:33.383 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.383 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.383 alo = 396, ahi = 1101
2025-07-02 04:52:33.383 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.383 blo = 396, bhi = 1101
2025-07-02 04:52:33.384
2025-07-02 04:52:33.384 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.384 g = []
2025-07-02 04:52:33.384 if alo < ahi:
2025-07-02 04:52:33.384 if blo < bhi:
2025-07-02 04:52:33.384 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.384 else:
2025-07-02 04:52:33.384 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.384 elif blo < bhi:
2025-07-02 04:52:33.384 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.384
2025-07-02 04:52:33.384 > yield from g
2025-07-02 04:52:33.384
2025-07-02 04:52:33.384 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.384 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.384
2025-07-02 04:52:33.384 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.384 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.384 alo = 396, ahi = 1101
2025-07-02 04:52:33.384 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.384 blo = 396, bhi = 1101
2025-07-02 04:52:33.384
2025-07-02 04:52:33.385 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.385 r"""
2025-07-02 04:52:33.385 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.385 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.385 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.385 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.385
2025-07-02 04:52:33.385 Example:
2025-07-02 04:52:33.385
2025-07-02 04:52:33.385 >>> d = Differ()
2025-07-02 04:52:33.385 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.385 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.385 >>> print(''.join(results), end="")
2025-07-02 04:52:33.385 - abcDefghiJkl
2025-07-02 04:52:33.385 + abcdefGhijkl
2025-07-02 04:52:33.385 """
2025-07-02 04:52:33.385
2025-07-02 04:52:33.385 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.385 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.386 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.386 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.386 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.386
2025-07-02 04:52:33.386 # search for the pair that matches best without being identical
2025-07-02 04:52:33.386 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.386 # on junk -- unless we have to)
2025-07-02 04:52:33.386 for j in range(blo, bhi):
2025-07-02 04:52:33.386 bj = b[j]
2025-07-02 04:52:33.386 cruncher.set_seq2(bj)
2025-07-02 04:52:33.386 for i in range(alo, ahi):
2025-07-02 04:52:33.386 ai = a[i]
2025-07-02 04:52:33.386 if ai == bj:
2025-07-02 04:52:33.386 if eqi is None:
2025-07-02 04:52:33.386 eqi, eqj = i, j
2025-07-02 04:52:33.386 continue
2025-07-02 04:52:33.386 cruncher.set_seq1(ai)
2025-07-02 04:52:33.386 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.386 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.386 # compares by a factor of 3.
2025-07-02 04:52:33.386 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.386 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.387 # of the computation is cached by cruncher
2025-07-02 04:52:33.387 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.387 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.387 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.387 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.387 if best_ratio < cutoff:
2025-07-02 04:52:33.387 # no non-identical "pretty close" pair
2025-07-02 04:52:33.387 if eqi is None:
2025-07-02 04:52:33.387 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.387 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.387 return
2025-07-02 04:52:33.387 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.387 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.387 else:
2025-07-02 04:52:33.387 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.387 eqi = None
2025-07-02 04:52:33.387
2025-07-02 04:52:33.387 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.387 # identical
2025-07-02 04:52:33.387
2025-07-02 04:52:33.388 # pump out diffs from before the synch point
2025-07-02 04:52:33.388 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.388
2025-07-02 04:52:33.388 # do intraline marking on the synch pair
2025-07-02 04:52:33.388 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.388 if eqi is None:
2025-07-02 04:52:33.388 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.388 atags = btags = ""
2025-07-02 04:52:33.388 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.388 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.388 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.388 if tag == 'replace':
2025-07-02 04:52:33.388 atags += '^' * la
2025-07-02 04:52:33.388 btags += '^' * lb
2025-07-02 04:52:33.388 elif tag == 'delete':
2025-07-02 04:52:33.388 atags += '-' * la
2025-07-02 04:52:33.388 elif tag == 'insert':
2025-07-02 04:52:33.388 btags += '+' * lb
2025-07-02 04:52:33.388 elif tag == 'equal':
2025-07-02 04:52:33.388 atags += ' ' * la
2025-07-02 04:52:33.388 btags += ' ' * lb
2025-07-02 04:52:33.389 else:
2025-07-02 04:52:33.389 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.389 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.389 else:
2025-07-02 04:52:33.389 # the synch pair is identical
2025-07-02 04:52:33.389 yield ' ' + aelt
2025-07-02 04:52:33.389
2025-07-02 04:52:33.389 # pump out diffs from after the synch point
2025-07-02 04:52:33.389 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.389
2025-07-02 04:52:33.389 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.389 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.389
2025-07-02 04:52:33.389 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.389 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.389 alo = 397, ahi = 1101
2025-07-02 04:52:33.389 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.389 blo = 397, bhi = 1101
2025-07-02 04:52:33.389
2025-07-02 04:52:33.389 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.390 g = []
2025-07-02 04:52:33.390 if alo < ahi:
2025-07-02 04:52:33.390 if blo < bhi:
2025-07-02 04:52:33.390 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.390 else:
2025-07-02 04:52:33.390 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.390 elif blo < bhi:
2025-07-02 04:52:33.390 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.390
2025-07-02 04:52:33.390 > yield from g
2025-07-02 04:52:33.390
2025-07-02 04:52:33.390 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.390 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.390
2025-07-02 04:52:33.390 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.390 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.390 alo = 397, ahi = 1101
2025-07-02 04:52:33.390 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.390 blo = 397, bhi = 1101
2025-07-02 04:52:33.390
2025-07-02 04:52:33.390 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.390 r"""
2025-07-02 04:52:33.391 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.391 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.391 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.391 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.391
2025-07-02 04:52:33.391 Example:
2025-07-02 04:52:33.391
2025-07-02 04:52:33.391 >>> d = Differ()
2025-07-02 04:52:33.391 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.391 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.391 >>> print(''.join(results), end="")
2025-07-02 04:52:33.391 - abcDefghiJkl
2025-07-02 04:52:33.391 + abcdefGhijkl
2025-07-02 04:52:33.391 """
2025-07-02 04:52:33.391
2025-07-02 04:52:33.391 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.391 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.391 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.391 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.392 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.392
2025-07-02 04:52:33.392 # search for the pair that matches best without being identical
2025-07-02 04:52:33.392 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.392 # on junk -- unless we have to)
2025-07-02 04:52:33.392 for j in range(blo, bhi):
2025-07-02 04:52:33.392 bj = b[j]
2025-07-02 04:52:33.392 cruncher.set_seq2(bj)
2025-07-02 04:52:33.392 for i in range(alo, ahi):
2025-07-02 04:52:33.392 ai = a[i]
2025-07-02 04:52:33.392 if ai == bj:
2025-07-02 04:52:33.392 if eqi is None:
2025-07-02 04:52:33.392 eqi, eqj = i, j
2025-07-02 04:52:33.392 continue
2025-07-02 04:52:33.392 cruncher.set_seq1(ai)
2025-07-02 04:52:33.392 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.392 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.392 # compares by a factor of 3.
2025-07-02 04:52:33.392 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.392 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.392 # of the computation is cached by cruncher
2025-07-02 04:52:33.392 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.393 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.393 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.393 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.393 if best_ratio < cutoff:
2025-07-02 04:52:33.393 # no non-identical "pretty close" pair
2025-07-02 04:52:33.393 if eqi is None:
2025-07-02 04:52:33.393 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.393 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.393 return
2025-07-02 04:52:33.393 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.393 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.393 else:
2025-07-02 04:52:33.393 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.393 eqi = None
2025-07-02 04:52:33.393
2025-07-02 04:52:33.393 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.393 # identical
2025-07-02 04:52:33.393
2025-07-02 04:52:33.393 # pump out diffs from before the synch point
2025-07-02 04:52:33.393 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.393
2025-07-02 04:52:33.394 # do intraline marking on the synch pair
2025-07-02 04:52:33.394 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.394 if eqi is None:
2025-07-02 04:52:33.394 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.394 atags = btags = ""
2025-07-02 04:52:33.394 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.394 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.394 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.394 if tag == 'replace':
2025-07-02 04:52:33.394 atags += '^' * la
2025-07-02 04:52:33.394 btags += '^' * lb
2025-07-02 04:52:33.394 elif tag == 'delete':
2025-07-02 04:52:33.394 atags += '-' * la
2025-07-02 04:52:33.394 elif tag == 'insert':
2025-07-02 04:52:33.394 btags += '+' * lb
2025-07-02 04:52:33.394 elif tag == 'equal':
2025-07-02 04:52:33.394 atags += ' ' * la
2025-07-02 04:52:33.394 btags += ' ' * lb
2025-07-02 04:52:33.394 else:
2025-07-02 04:52:33.394 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.394 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.395 else:
2025-07-02 04:52:33.395 # the synch pair is identical
2025-07-02 04:52:33.395 yield ' ' + aelt
2025-07-02 04:52:33.395
2025-07-02 04:52:33.395 # pump out diffs from after the synch point
2025-07-02 04:52:33.395 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.395
2025-07-02 04:52:33.395 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.395 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.395
2025-07-02 04:52:33.395 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.395 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.395 alo = 400, ahi = 1101
2025-07-02 04:52:33.395 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.395 blo = 400, bhi = 1101
2025-07-02 04:52:33.395
2025-07-02 04:52:33.395 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.395 g = []
2025-07-02 04:52:33.395 if alo < ahi:
2025-07-02 04:52:33.395 if blo < bhi:
2025-07-02 04:52:33.396 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.396 else:
2025-07-02 04:52:33.396 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.396 elif blo < bhi:
2025-07-02 04:52:33.396 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.396
2025-07-02 04:52:33.396 > yield from g
2025-07-02 04:52:33.396
2025-07-02 04:52:33.396 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.396 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.396
2025-07-02 04:52:33.396 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.396 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.396 alo = 400, ahi = 1101
2025-07-02 04:52:33.396 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.396 blo = 400, bhi = 1101
2025-07-02 04:52:33.396
2025-07-02 04:52:33.396 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.396 r"""
2025-07-02 04:52:33.396 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.397 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.397 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.397 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.397
2025-07-02 04:52:33.397 Example:
2025-07-02 04:52:33.397
2025-07-02 04:52:33.397 >>> d = Differ()
2025-07-02 04:52:33.397 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.397 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.397 >>> print(''.join(results), end="")
2025-07-02 04:52:33.397 - abcDefghiJkl
2025-07-02 04:52:33.397 + abcdefGhijkl
2025-07-02 04:52:33.397 """
2025-07-02 04:52:33.397
2025-07-02 04:52:33.397 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.397 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.397 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.398 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.398 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.398
2025-07-02 04:52:33.398 # search for the pair that matches best without being identical
2025-07-02 04:52:33.398 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.398 # on junk -- unless we have to)
2025-07-02 04:52:33.398 for j in range(blo, bhi):
2025-07-02 04:52:33.398 bj = b[j]
2025-07-02 04:52:33.398 cruncher.set_seq2(bj)
2025-07-02 04:52:33.398 for i in range(alo, ahi):
2025-07-02 04:52:33.398 ai = a[i]
2025-07-02 04:52:33.398 if ai == bj:
2025-07-02 04:52:33.398 if eqi is None:
2025-07-02 04:52:33.398 eqi, eqj = i, j
2025-07-02 04:52:33.398 continue
2025-07-02 04:52:33.398 cruncher.set_seq1(ai)
2025-07-02 04:52:33.398 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.398 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.399 # compares by a factor of 3.
2025-07-02 04:52:33.399 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.399 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.399 # of the computation is cached by cruncher
2025-07-02 04:52:33.399 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.399 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.399 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.399 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.399 if best_ratio < cutoff:
2025-07-02 04:52:33.399 # no non-identical "pretty close" pair
2025-07-02 04:52:33.399 if eqi is None:
2025-07-02 04:52:33.399 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.399 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.399 return
2025-07-02 04:52:33.399 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.399 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.399 else:
2025-07-02 04:52:33.399 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.399 eqi = None
2025-07-02 04:52:33.399
2025-07-02 04:52:33.399 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.400 # identical
2025-07-02 04:52:33.400
2025-07-02 04:52:33.400 # pump out diffs from before the synch point
2025-07-02 04:52:33.400 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.400
2025-07-02 04:52:33.400 # do intraline marking on the synch pair
2025-07-02 04:52:33.400 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.400 if eqi is None:
2025-07-02 04:52:33.400 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.400 atags = btags = ""
2025-07-02 04:52:33.400 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.400 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.400 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.400 if tag == 'replace':
2025-07-02 04:52:33.400 atags += '^' * la
2025-07-02 04:52:33.400 btags += '^' * lb
2025-07-02 04:52:33.400 elif tag == 'delete':
2025-07-02 04:52:33.400 atags += '-' * la
2025-07-02 04:52:33.400 elif tag == 'insert':
2025-07-02 04:52:33.400 btags += '+' * lb
2025-07-02 04:52:33.401 elif tag == 'equal':
2025-07-02 04:52:33.401 atags += ' ' * la
2025-07-02 04:52:33.401 btags += ' ' * lb
2025-07-02 04:52:33.401 else:
2025-07-02 04:52:33.401 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.401 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.401 else:
2025-07-02 04:52:33.401 # the synch pair is identical
2025-07-02 04:52:33.401 yield ' ' + aelt
2025-07-02 04:52:33.401
2025-07-02 04:52:33.401 # pump out diffs from after the synch point
2025-07-02 04:52:33.401 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.401
2025-07-02 04:52:33.401 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.401 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.401
2025-07-02 04:52:33.401 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.401 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.401 alo = 401, ahi = 1101
2025-07-02 04:52:33.401 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.401 blo = 401, bhi = 1101
2025-07-02 04:52:33.402
2025-07-02 04:52:33.402 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.402 g = []
2025-07-02 04:52:33.402 if alo < ahi:
2025-07-02 04:52:33.402 if blo < bhi:
2025-07-02 04:52:33.402 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.402 else:
2025-07-02 04:52:33.402 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.402 elif blo < bhi:
2025-07-02 04:52:33.402 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.402
2025-07-02 04:52:33.402 > yield from g
2025-07-02 04:52:33.402
2025-07-02 04:52:33.402 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.402 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.402
2025-07-02 04:52:33.402 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.402 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.402 alo = 401, ahi = 1101
2025-07-02 04:52:33.402 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.403 blo = 401, bhi = 1101
2025-07-02 04:52:33.403
2025-07-02 04:52:33.403 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.403 r"""
2025-07-02 04:52:33.403 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.403 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.403 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.403 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.403
2025-07-02 04:52:33.403 Example:
2025-07-02 04:52:33.403
2025-07-02 04:52:33.403 >>> d = Differ()
2025-07-02 04:52:33.403 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.403 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.403 >>> print(''.join(results), end="")
2025-07-02 04:52:33.403 - abcDefghiJkl
2025-07-02 04:52:33.403 + abcdefGhijkl
2025-07-02 04:52:33.403 """
2025-07-02 04:52:33.403
2025-07-02 04:52:33.404 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.404 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.404 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.404 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.404 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.404
2025-07-02 04:52:33.404 # search for the pair that matches best without being identical
2025-07-02 04:52:33.404 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.404 # on junk -- unless we have to)
2025-07-02 04:52:33.404 for j in range(blo, bhi):
2025-07-02 04:52:33.404 bj = b[j]
2025-07-02 04:52:33.404 cruncher.set_seq2(bj)
2025-07-02 04:52:33.404 for i in range(alo, ahi):
2025-07-02 04:52:33.404 ai = a[i]
2025-07-02 04:52:33.404 if ai == bj:
2025-07-02 04:52:33.404 if eqi is None:
2025-07-02 04:52:33.404 eqi, eqj = i, j
2025-07-02 04:52:33.404 continue
2025-07-02 04:52:33.404 cruncher.set_seq1(ai)
2025-07-02 04:52:33.404 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.405 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.405 # compares by a factor of 3.
2025-07-02 04:52:33.405 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.405 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.405 # of the computation is cached by cruncher
2025-07-02 04:52:33.405 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.405 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.405 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.405 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.405 if best_ratio < cutoff:
2025-07-02 04:52:33.405 # no non-identical "pretty close" pair
2025-07-02 04:52:33.405 if eqi is None:
2025-07-02 04:52:33.405 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.405 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.405 return
2025-07-02 04:52:33.405 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.405 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.405 else:
2025-07-02 04:52:33.405 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.405 eqi = None
2025-07-02 04:52:33.405
2025-07-02 04:52:33.406 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.406 # identical
2025-07-02 04:52:33.406
2025-07-02 04:52:33.406 # pump out diffs from before the synch point
2025-07-02 04:52:33.406 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.406
2025-07-02 04:52:33.406 # do intraline marking on the synch pair
2025-07-02 04:52:33.406 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.406 if eqi is None:
2025-07-02 04:52:33.406 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.406 atags = btags = ""
2025-07-02 04:52:33.406 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.406 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.406 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.406 if tag == 'replace':
2025-07-02 04:52:33.406 atags += '^' * la
2025-07-02 04:52:33.406 btags += '^' * lb
2025-07-02 04:52:33.406 elif tag == 'delete':
2025-07-02 04:52:33.406 atags += '-' * la
2025-07-02 04:52:33.406 elif tag == 'insert':
2025-07-02 04:52:33.407 btags += '+' * lb
2025-07-02 04:52:33.407 elif tag == 'equal':
2025-07-02 04:52:33.407 atags += ' ' * la
2025-07-02 04:52:33.407 btags += ' ' * lb
2025-07-02 04:52:33.407 else:
2025-07-02 04:52:33.407 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.407 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.407 else:
2025-07-02 04:52:33.407 # the synch pair is identical
2025-07-02 04:52:33.407 yield ' ' + aelt
2025-07-02 04:52:33.407
2025-07-02 04:52:33.407 # pump out diffs from after the synch point
2025-07-02 04:52:33.407 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.407
2025-07-02 04:52:33.407 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.407 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.407
2025-07-02 04:52:33.407 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.407 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.407 alo = 402, ahi = 1101
2025-07-02 04:52:33.407 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.408 blo = 402, bhi = 1101
2025-07-02 04:52:33.408
2025-07-02 04:52:33.408 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.408 g = []
2025-07-02 04:52:33.408 if alo < ahi:
2025-07-02 04:52:33.408 if blo < bhi:
2025-07-02 04:52:33.408 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.408 else:
2025-07-02 04:52:33.408 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.408 elif blo < bhi:
2025-07-02 04:52:33.408 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.408
2025-07-02 04:52:33.408 > yield from g
2025-07-02 04:52:33.408
2025-07-02 04:52:33.408 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.408 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.408
2025-07-02 04:52:33.408 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.408 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.408 alo = 402, ahi = 1101
2025-07-02 04:52:33.409 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.409 blo = 402, bhi = 1101
2025-07-02 04:52:33.409
2025-07-02 04:52:33.409 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.409 r"""
2025-07-02 04:52:33.409 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.409 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.409 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.409 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.409
2025-07-02 04:52:33.409 Example:
2025-07-02 04:52:33.409
2025-07-02 04:52:33.409 >>> d = Differ()
2025-07-02 04:52:33.409 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.409 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.409 >>> print(''.join(results), end="")
2025-07-02 04:52:33.409 - abcDefghiJkl
2025-07-02 04:52:33.409 + abcdefGhijkl
2025-07-02 04:52:33.409 """
2025-07-02 04:52:33.410
2025-07-02 04:52:33.410 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.410 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.410 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.410 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.410 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.410
2025-07-02 04:52:33.410 # search for the pair that matches best without being identical
2025-07-02 04:52:33.410 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.410 # on junk -- unless we have to)
2025-07-02 04:52:33.410 for j in range(blo, bhi):
2025-07-02 04:52:33.410 bj = b[j]
2025-07-02 04:52:33.410 cruncher.set_seq2(bj)
2025-07-02 04:52:33.410 for i in range(alo, ahi):
2025-07-02 04:52:33.410 ai = a[i]
2025-07-02 04:52:33.410 if ai == bj:
2025-07-02 04:52:33.410 if eqi is None:
2025-07-02 04:52:33.410 eqi, eqj = i, j
2025-07-02 04:52:33.410 continue
2025-07-02 04:52:33.410 cruncher.set_seq1(ai)
2025-07-02 04:52:33.410 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.411 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.411 # compares by a factor of 3.
2025-07-02 04:52:33.411 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.411 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.411 # of the computation is cached by cruncher
2025-07-02 04:52:33.411 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.411 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.411 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.411 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.411 if best_ratio < cutoff:
2025-07-02 04:52:33.411 # no non-identical "pretty close" pair
2025-07-02 04:52:33.411 if eqi is None:
2025-07-02 04:52:33.411 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.411 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.411 return
2025-07-02 04:52:33.411 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.411 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.411 else:
2025-07-02 04:52:33.411 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.411 eqi = None
2025-07-02 04:52:33.412
2025-07-02 04:52:33.412 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.412 # identical
2025-07-02 04:52:33.412
2025-07-02 04:52:33.412 # pump out diffs from before the synch point
2025-07-02 04:52:33.412 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.412
2025-07-02 04:52:33.412 # do intraline marking on the synch pair
2025-07-02 04:52:33.412 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.412 if eqi is None:
2025-07-02 04:52:33.412 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.412 atags = btags = ""
2025-07-02 04:52:33.412 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.412 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.412 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.412 if tag == 'replace':
2025-07-02 04:52:33.412 atags += '^' * la
2025-07-02 04:52:33.412 btags += '^' * lb
2025-07-02 04:52:33.412 elif tag == 'delete':
2025-07-02 04:52:33.413 atags += '-' * la
2025-07-02 04:52:33.413 elif tag == 'insert':
2025-07-02 04:52:33.413 btags += '+' * lb
2025-07-02 04:52:33.413 elif tag == 'equal':
2025-07-02 04:52:33.413 atags += ' ' * la
2025-07-02 04:52:33.413 btags += ' ' * lb
2025-07-02 04:52:33.413 else:
2025-07-02 04:52:33.413 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.413 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.413 else:
2025-07-02 04:52:33.413 # the synch pair is identical
2025-07-02 04:52:33.413 yield ' ' + aelt
2025-07-02 04:52:33.413
2025-07-02 04:52:33.413 # pump out diffs from after the synch point
2025-07-02 04:52:33.413 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.413
2025-07-02 04:52:33.413 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.413 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.413
2025-07-02 04:52:33.413 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.413 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.414 alo = 403, ahi = 1101
2025-07-02 04:52:33.414 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.414 blo = 403, bhi = 1101
2025-07-02 04:52:33.414
2025-07-02 04:52:33.414 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.414 g = []
2025-07-02 04:52:33.414 if alo < ahi:
2025-07-02 04:52:33.414 if blo < bhi:
2025-07-02 04:52:33.414 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.414 else:
2025-07-02 04:52:33.414 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.414 elif blo < bhi:
2025-07-02 04:52:33.414 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.414
2025-07-02 04:52:33.414 > yield from g
2025-07-02 04:52:33.414
2025-07-02 04:52:33.414 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.414 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.414
2025-07-02 04:52:33.414 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.415 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.415 alo = 403, ahi = 1101
2025-07-02 04:52:33.415 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.415 blo = 403, bhi = 1101
2025-07-02 04:52:33.415
2025-07-02 04:52:33.415 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.415 r"""
2025-07-02 04:52:33.415 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.415 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.415 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.415 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.415
2025-07-02 04:52:33.415 Example:
2025-07-02 04:52:33.415
2025-07-02 04:52:33.415 >>> d = Differ()
2025-07-02 04:52:33.415 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.415 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.415 >>> print(''.join(results), end="")
2025-07-02 04:52:33.415 - abcDefghiJkl
2025-07-02 04:52:33.415 + abcdefGhijkl
2025-07-02 04:52:33.416 """
2025-07-02 04:52:33.416
2025-07-02 04:52:33.416 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.416 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.416 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.416 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.416 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.416
2025-07-02 04:52:33.416 # search for the pair that matches best without being identical
2025-07-02 04:52:33.416 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.416 # on junk -- unless we have to)
2025-07-02 04:52:33.416 for j in range(blo, bhi):
2025-07-02 04:52:33.416 bj = b[j]
2025-07-02 04:52:33.416 cruncher.set_seq2(bj)
2025-07-02 04:52:33.416 for i in range(alo, ahi):
2025-07-02 04:52:33.416 ai = a[i]
2025-07-02 04:52:33.416 if ai == bj:
2025-07-02 04:52:33.416 if eqi is None:
2025-07-02 04:52:33.416 eqi, eqj = i, j
2025-07-02 04:52:33.416 continue
2025-07-02 04:52:33.417 cruncher.set_seq1(ai)
2025-07-02 04:52:33.417 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.417 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.417 # compares by a factor of 3.
2025-07-02 04:52:33.417 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.417 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.417 # of the computation is cached by cruncher
2025-07-02 04:52:33.417 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.417 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.417 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.417 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.417 if best_ratio < cutoff:
2025-07-02 04:52:33.417 # no non-identical "pretty close" pair
2025-07-02 04:52:33.417 if eqi is None:
2025-07-02 04:52:33.417 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.417 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.417 return
2025-07-02 04:52:33.417 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.417 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.417 else:
2025-07-02 04:52:33.418 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.418 eqi = None
2025-07-02 04:52:33.418
2025-07-02 04:52:33.418 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.418 # identical
2025-07-02 04:52:33.418
2025-07-02 04:52:33.418 # pump out diffs from before the synch point
2025-07-02 04:52:33.418 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.418
2025-07-02 04:52:33.418 # do intraline marking on the synch pair
2025-07-02 04:52:33.418 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.418 if eqi is None:
2025-07-02 04:52:33.418 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.418 atags = btags = ""
2025-07-02 04:52:33.418 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.418 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.418 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.418 if tag == 'replace':
2025-07-02 04:52:33.418 atags += '^' * la
2025-07-02 04:52:33.418 btags += '^' * lb
2025-07-02 04:52:33.418 elif tag == 'delete':
2025-07-02 04:52:33.419 atags += '-' * la
2025-07-02 04:52:33.419 elif tag == 'insert':
2025-07-02 04:52:33.419 btags += '+' * lb
2025-07-02 04:52:33.419 elif tag == 'equal':
2025-07-02 04:52:33.419 atags += ' ' * la
2025-07-02 04:52:33.419 btags += ' ' * lb
2025-07-02 04:52:33.419 else:
2025-07-02 04:52:33.419 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.419 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.419 else:
2025-07-02 04:52:33.419 # the synch pair is identical
2025-07-02 04:52:33.419 yield ' ' + aelt
2025-07-02 04:52:33.419
2025-07-02 04:52:33.419 # pump out diffs from after the synch point
2025-07-02 04:52:33.419 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.419
2025-07-02 04:52:33.419 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.419 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.419
2025-07-02 04:52:33.419 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.420 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.420 alo = 404, ahi = 1101
2025-07-02 04:52:33.420 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.420 blo = 404, bhi = 1101
2025-07-02 04:52:33.420
2025-07-02 04:52:33.420 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.420 g = []
2025-07-02 04:52:33.420 if alo < ahi:
2025-07-02 04:52:33.420 if blo < bhi:
2025-07-02 04:52:33.420 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.420 else:
2025-07-02 04:52:33.420 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.420 elif blo < bhi:
2025-07-02 04:52:33.420 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.420
2025-07-02 04:52:33.420 > yield from g
2025-07-02 04:52:33.420
2025-07-02 04:52:33.420 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.420 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.420
2025-07-02 04:52:33.420 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.421 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.421 alo = 404, ahi = 1101
2025-07-02 04:52:33.421 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.421 blo = 404, bhi = 1101
2025-07-02 04:52:33.421
2025-07-02 04:52:33.421 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.421 r"""
2025-07-02 04:52:33.421 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.421 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.421 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.421 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.421
2025-07-02 04:52:33.421 Example:
2025-07-02 04:52:33.421
2025-07-02 04:52:33.421 >>> d = Differ()
2025-07-02 04:52:33.421 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.421 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.421 >>> print(''.join(results), end="")
2025-07-02 04:52:33.421 - abcDefghiJkl
2025-07-02 04:52:33.422 + abcdefGhijkl
2025-07-02 04:52:33.422 """
2025-07-02 04:52:33.422
2025-07-02 04:52:33.422 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.422 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.422 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.422 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.422 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.422
2025-07-02 04:52:33.422 # search for the pair that matches best without being identical
2025-07-02 04:52:33.422 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.422 # on junk -- unless we have to)
2025-07-02 04:52:33.422 for j in range(blo, bhi):
2025-07-02 04:52:33.422 bj = b[j]
2025-07-02 04:52:33.422 cruncher.set_seq2(bj)
2025-07-02 04:52:33.422 for i in range(alo, ahi):
2025-07-02 04:52:33.422 ai = a[i]
2025-07-02 04:52:33.422 if ai == bj:
2025-07-02 04:52:33.423 if eqi is None:
2025-07-02 04:52:33.423 eqi, eqj = i, j
2025-07-02 04:52:33.423 continue
2025-07-02 04:52:33.423 cruncher.set_seq1(ai)
2025-07-02 04:52:33.423 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.423 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.423 # compares by a factor of 3.
2025-07-02 04:52:33.423 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.423 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.423 # of the computation is cached by cruncher
2025-07-02 04:52:33.423 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.423 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.423 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.423 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.423 if best_ratio < cutoff:
2025-07-02 04:52:33.423 # no non-identical "pretty close" pair
2025-07-02 04:52:33.423 if eqi is None:
2025-07-02 04:52:33.423 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.423 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.423 return
2025-07-02 04:52:33.423 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.424 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.424 else:
2025-07-02 04:52:33.424 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.424 eqi = None
2025-07-02 04:52:33.424
2025-07-02 04:52:33.424 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.424 # identical
2025-07-02 04:52:33.424
2025-07-02 04:52:33.424 # pump out diffs from before the synch point
2025-07-02 04:52:33.424 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.424
2025-07-02 04:52:33.424 # do intraline marking on the synch pair
2025-07-02 04:52:33.424 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.424 if eqi is None:
2025-07-02 04:52:33.424 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.424 atags = btags = ""
2025-07-02 04:52:33.424 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.424 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.424 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.424 if tag == 'replace':
2025-07-02 04:52:33.424 atags += '^' * la
2025-07-02 04:52:33.425 btags += '^' * lb
2025-07-02 04:52:33.425 elif tag == 'delete':
2025-07-02 04:52:33.425 atags += '-' * la
2025-07-02 04:52:33.425 elif tag == 'insert':
2025-07-02 04:52:33.425 btags += '+' * lb
2025-07-02 04:52:33.425 elif tag == 'equal':
2025-07-02 04:52:33.425 atags += ' ' * la
2025-07-02 04:52:33.425 btags += ' ' * lb
2025-07-02 04:52:33.425 else:
2025-07-02 04:52:33.425 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.425 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.425 else:
2025-07-02 04:52:33.425 # the synch pair is identical
2025-07-02 04:52:33.425 yield ' ' + aelt
2025-07-02 04:52:33.425
2025-07-02 04:52:33.425 # pump out diffs from after the synch point
2025-07-02 04:52:33.425 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.425
2025-07-02 04:52:33.425 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.425 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.425
2025-07-02 04:52:33.425 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.426 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.426 alo = 405, ahi = 1101
2025-07-02 04:52:33.426 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.426 blo = 405, bhi = 1101
2025-07-02 04:52:33.426
2025-07-02 04:52:33.426 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.426 g = []
2025-07-02 04:52:33.426 if alo < ahi:
2025-07-02 04:52:33.426 if blo < bhi:
2025-07-02 04:52:33.426 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.426 else:
2025-07-02 04:52:33.426 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.426 elif blo < bhi:
2025-07-02 04:52:33.426 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.426
2025-07-02 04:52:33.426 > yield from g
2025-07-02 04:52:33.426
2025-07-02 04:52:33.426 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.426 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.426
2025-07-02 04:52:33.427 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.427 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.427 alo = 405, ahi = 1101
2025-07-02 04:52:33.427 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.427 blo = 405, bhi = 1101
2025-07-02 04:52:33.427
2025-07-02 04:52:33.427 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.427 r"""
2025-07-02 04:52:33.427 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.427 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.427 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.427 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.427
2025-07-02 04:52:33.427 Example:
2025-07-02 04:52:33.427
2025-07-02 04:52:33.427 >>> d = Differ()
2025-07-02 04:52:33.427 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.427 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.427 >>> print(''.join(results), end="")
2025-07-02 04:52:33.427 - abcDefghiJkl
2025-07-02 04:52:33.427 + abcdefGhijkl
2025-07-02 04:52:33.428 """
2025-07-02 04:52:33.428
2025-07-02 04:52:33.428 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.428 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.428 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.428 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.428 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.428
2025-07-02 04:52:33.428 # search for the pair that matches best without being identical
2025-07-02 04:52:33.428 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.428 # on junk -- unless we have to)
2025-07-02 04:52:33.428 for j in range(blo, bhi):
2025-07-02 04:52:33.428 bj = b[j]
2025-07-02 04:52:33.428 cruncher.set_seq2(bj)
2025-07-02 04:52:33.428 for i in range(alo, ahi):
2025-07-02 04:52:33.428 ai = a[i]
2025-07-02 04:52:33.428 if ai == bj:
2025-07-02 04:52:33.429 if eqi is None:
2025-07-02 04:52:33.429 eqi, eqj = i, j
2025-07-02 04:52:33.429 continue
2025-07-02 04:52:33.429 cruncher.set_seq1(ai)
2025-07-02 04:52:33.429 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.429 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.429 # compares by a factor of 3.
2025-07-02 04:52:33.429 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.429 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.429 # of the computation is cached by cruncher
2025-07-02 04:52:33.429 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.429 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.429 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.429 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.429 if best_ratio < cutoff:
2025-07-02 04:52:33.429 # no non-identical "pretty close" pair
2025-07-02 04:52:33.429 if eqi is None:
2025-07-02 04:52:33.429 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.429 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.430 return
2025-07-02 04:52:33.430 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.430 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.430 else:
2025-07-02 04:52:33.430 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.430 eqi = None
2025-07-02 04:52:33.430
2025-07-02 04:52:33.430 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.430 # identical
2025-07-02 04:52:33.430
2025-07-02 04:52:33.430 # pump out diffs from before the synch point
2025-07-02 04:52:33.430 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.430
2025-07-02 04:52:33.430 # do intraline marking on the synch pair
2025-07-02 04:52:33.430 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.430 if eqi is None:
2025-07-02 04:52:33.430 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.430 atags = btags = ""
2025-07-02 04:52:33.430 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.430 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.430 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.431 if tag == 'replace':
2025-07-02 04:52:33.431 atags += '^' * la
2025-07-02 04:52:33.431 btags += '^' * lb
2025-07-02 04:52:33.431 elif tag == 'delete':
2025-07-02 04:52:33.431 atags += '-' * la
2025-07-02 04:52:33.431 elif tag == 'insert':
2025-07-02 04:52:33.431 btags += '+' * lb
2025-07-02 04:52:33.431 elif tag == 'equal':
2025-07-02 04:52:33.431 atags += ' ' * la
2025-07-02 04:52:33.431 btags += ' ' * lb
2025-07-02 04:52:33.431 else:
2025-07-02 04:52:33.431 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.431 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.431 else:
2025-07-02 04:52:33.431 # the synch pair is identical
2025-07-02 04:52:33.431 yield ' ' + aelt
2025-07-02 04:52:33.431
2025-07-02 04:52:33.431 # pump out diffs from after the synch point
2025-07-02 04:52:33.431 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.431
2025-07-02 04:52:33.432 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.432 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.432
2025-07-02 04:52:33.432 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.432 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.432 alo = 406, ahi = 1101
2025-07-02 04:52:33.432 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.432 blo = 406, bhi = 1101
2025-07-02 04:52:33.432
2025-07-02 04:52:33.432 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.432 g = []
2025-07-02 04:52:33.432 if alo < ahi:
2025-07-02 04:52:33.432 if blo < bhi:
2025-07-02 04:52:33.432 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.432 else:
2025-07-02 04:52:33.432 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.432 elif blo < bhi:
2025-07-02 04:52:33.432 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.432
2025-07-02 04:52:33.432 > yield from g
2025-07-02 04:52:33.433
2025-07-02 04:52:33.433 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.433 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.433
2025-07-02 04:52:33.433 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.433 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.433 alo = 406, ahi = 1101
2025-07-02 04:52:33.433 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.433 blo = 406, bhi = 1101
2025-07-02 04:52:33.433
2025-07-02 04:52:33.433 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.433 r"""
2025-07-02 04:52:33.433 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.433 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.433 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.433 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.433
2025-07-02 04:52:33.433 Example:
2025-07-02 04:52:33.433
2025-07-02 04:52:33.433 >>> d = Differ()
2025-07-02 04:52:33.434 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.434 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.434 >>> print(''.join(results), end="")
2025-07-02 04:52:33.434 - abcDefghiJkl
2025-07-02 04:52:33.434 + abcdefGhijkl
2025-07-02 04:52:33.434 """
2025-07-02 04:52:33.434
2025-07-02 04:52:33.434 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.434 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.434 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.434 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.434 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.434
2025-07-02 04:52:33.434 # search for the pair that matches best without being identical
2025-07-02 04:52:33.434 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.434 # on junk -- unless we have to)
2025-07-02 04:52:33.434 for j in range(blo, bhi):
2025-07-02 04:52:33.434 bj = b[j]
2025-07-02 04:52:33.435 cruncher.set_seq2(bj)
2025-07-02 04:52:33.435 for i in range(alo, ahi):
2025-07-02 04:52:33.435 ai = a[i]
2025-07-02 04:52:33.435 if ai == bj:
2025-07-02 04:52:33.435 if eqi is None:
2025-07-02 04:52:33.435 eqi, eqj = i, j
2025-07-02 04:52:33.435 continue
2025-07-02 04:52:33.435 cruncher.set_seq1(ai)
2025-07-02 04:52:33.435 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.435 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.435 # compares by a factor of 3.
2025-07-02 04:52:33.435 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.435 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.435 # of the computation is cached by cruncher
2025-07-02 04:52:33.435 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.435 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.435 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.435 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.435 if best_ratio < cutoff:
2025-07-02 04:52:33.435 # no non-identical "pretty close" pair
2025-07-02 04:52:33.436 if eqi is None:
2025-07-02 04:52:33.436 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.436 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.436 return
2025-07-02 04:52:33.436 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.436 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.436 else:
2025-07-02 04:52:33.436 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.436 eqi = None
2025-07-02 04:52:33.436
2025-07-02 04:52:33.436 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.436 # identical
2025-07-02 04:52:33.436
2025-07-02 04:52:33.436 # pump out diffs from before the synch point
2025-07-02 04:52:33.436 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.436
2025-07-02 04:52:33.436 # do intraline marking on the synch pair
2025-07-02 04:52:33.436 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.436 if eqi is None:
2025-07-02 04:52:33.436 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.436 atags = btags = ""
2025-07-02 04:52:33.437 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.437 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.437 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.437 if tag == 'replace':
2025-07-02 04:52:33.437 atags += '^' * la
2025-07-02 04:52:33.437 btags += '^' * lb
2025-07-02 04:52:33.437 elif tag == 'delete':
2025-07-02 04:52:33.437 atags += '-' * la
2025-07-02 04:52:33.437 elif tag == 'insert':
2025-07-02 04:52:33.437 btags += '+' * lb
2025-07-02 04:52:33.437 elif tag == 'equal':
2025-07-02 04:52:33.437 atags += ' ' * la
2025-07-02 04:52:33.437 btags += ' ' * lb
2025-07-02 04:52:33.437 else:
2025-07-02 04:52:33.437 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.437 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.437 else:
2025-07-02 04:52:33.437 # the synch pair is identical
2025-07-02 04:52:33.437 yield ' ' + aelt
2025-07-02 04:52:33.437
2025-07-02 04:52:33.438 # pump out diffs from after the synch point
2025-07-02 04:52:33.438 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.438
2025-07-02 04:52:33.438 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.438 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.438
2025-07-02 04:52:33.438 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.438 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.438 alo = 407, ahi = 1101
2025-07-02 04:52:33.438 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.438 blo = 407, bhi = 1101
2025-07-02 04:52:33.438
2025-07-02 04:52:33.438 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.438 g = []
2025-07-02 04:52:33.438 if alo < ahi:
2025-07-02 04:52:33.438 if blo < bhi:
2025-07-02 04:52:33.438 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.438 else:
2025-07-02 04:52:33.438 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.438 elif blo < bhi:
2025-07-02 04:52:33.439 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.439
2025-07-02 04:52:33.439 > yield from g
2025-07-02 04:52:33.439
2025-07-02 04:52:33.439 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.439 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.439
2025-07-02 04:52:33.439 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.439 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.439 alo = 407, ahi = 1101
2025-07-02 04:52:33.439 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.439 blo = 407, bhi = 1101
2025-07-02 04:52:33.439
2025-07-02 04:52:33.439 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.439 r"""
2025-07-02 04:52:33.439 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.439 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.439 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.439 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.439
2025-07-02 04:52:33.440 Example:
2025-07-02 04:52:33.440
2025-07-02 04:52:33.440 >>> d = Differ()
2025-07-02 04:52:33.440 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.440 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.440 >>> print(''.join(results), end="")
2025-07-02 04:52:33.440 - abcDefghiJkl
2025-07-02 04:52:33.440 + abcdefGhijkl
2025-07-02 04:52:33.440 """
2025-07-02 04:52:33.440
2025-07-02 04:52:33.440 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.440 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.440 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.440 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.440 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.440
2025-07-02 04:52:33.440 # search for the pair that matches best without being identical
2025-07-02 04:52:33.440 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.440 # on junk -- unless we have to)
2025-07-02 04:52:33.441 for j in range(blo, bhi):
2025-07-02 04:52:33.441 bj = b[j]
2025-07-02 04:52:33.441 cruncher.set_seq2(bj)
2025-07-02 04:52:33.441 for i in range(alo, ahi):
2025-07-02 04:52:33.441 ai = a[i]
2025-07-02 04:52:33.441 if ai == bj:
2025-07-02 04:52:33.441 if eqi is None:
2025-07-02 04:52:33.441 eqi, eqj = i, j
2025-07-02 04:52:33.441 continue
2025-07-02 04:52:33.441 cruncher.set_seq1(ai)
2025-07-02 04:52:33.441 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.441 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.441 # compares by a factor of 3.
2025-07-02 04:52:33.441 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.441 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.441 # of the computation is cached by cruncher
2025-07-02 04:52:33.441 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.441 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.441 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.441 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.442 if best_ratio < cutoff:
2025-07-02 04:52:33.442 # no non-identical "pretty close" pair
2025-07-02 04:52:33.442 if eqi is None:
2025-07-02 04:52:33.442 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.442 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.442 return
2025-07-02 04:52:33.442 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.442 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.442 else:
2025-07-02 04:52:33.442 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.442 eqi = None
2025-07-02 04:52:33.442
2025-07-02 04:52:33.442 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.442 # identical
2025-07-02 04:52:33.442
2025-07-02 04:52:33.442 # pump out diffs from before the synch point
2025-07-02 04:52:33.442 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.442
2025-07-02 04:52:33.442 # do intraline marking on the synch pair
2025-07-02 04:52:33.443 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.443 if eqi is None:
2025-07-02 04:52:33.443 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.443 atags = btags = ""
2025-07-02 04:52:33.443 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.443 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.443 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.443 if tag == 'replace':
2025-07-02 04:52:33.443 atags += '^' * la
2025-07-02 04:52:33.443 btags += '^' * lb
2025-07-02 04:52:33.443 elif tag == 'delete':
2025-07-02 04:52:33.443 atags += '-' * la
2025-07-02 04:52:33.443 elif tag == 'insert':
2025-07-02 04:52:33.443 btags += '+' * lb
2025-07-02 04:52:33.443 elif tag == 'equal':
2025-07-02 04:52:33.443 atags += ' ' * la
2025-07-02 04:52:33.443 btags += ' ' * lb
2025-07-02 04:52:33.443 else:
2025-07-02 04:52:33.443 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.443 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.443 else:
2025-07-02 04:52:33.444 # the synch pair is identical
2025-07-02 04:52:33.444 yield ' ' + aelt
2025-07-02 04:52:33.444
2025-07-02 04:52:33.444 # pump out diffs from after the synch point
2025-07-02 04:52:33.444 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.444
2025-07-02 04:52:33.444 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.444 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.444
2025-07-02 04:52:33.444 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.444 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.444 alo = 408, ahi = 1101
2025-07-02 04:52:33.444 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.444 blo = 408, bhi = 1101
2025-07-02 04:52:33.444
2025-07-02 04:52:33.444 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.444 g = []
2025-07-02 04:52:33.444 if alo < ahi:
2025-07-02 04:52:33.445 if blo < bhi:
2025-07-02 04:52:33.445 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.445 else:
2025-07-02 04:52:33.445 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.445 elif blo < bhi:
2025-07-02 04:52:33.445 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.445
2025-07-02 04:52:33.445 > yield from g
2025-07-02 04:52:33.445
2025-07-02 04:52:33.445 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.445 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.445
2025-07-02 04:52:33.445 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.445 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.445 alo = 408, ahi = 1101
2025-07-02 04:52:33.445 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.445 blo = 408, bhi = 1101
2025-07-02 04:52:33.445
2025-07-02 04:52:33.445 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.445 r"""
2025-07-02 04:52:33.445 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.446 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.446 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.446 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.446
2025-07-02 04:52:33.446 Example:
2025-07-02 04:52:33.446
2025-07-02 04:52:33.446 >>> d = Differ()
2025-07-02 04:52:33.446 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.446 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.446 >>> print(''.join(results), end="")
2025-07-02 04:52:33.446 - abcDefghiJkl
2025-07-02 04:52:33.446 + abcdefGhijkl
2025-07-02 04:52:33.446 """
2025-07-02 04:52:33.446
2025-07-02 04:52:33.446 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.446 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.446 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.447 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.447 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.447
2025-07-02 04:52:33.447 # search for the pair that matches best without being identical
2025-07-02 04:52:33.447 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.447 # on junk -- unless we have to)
2025-07-02 04:52:33.447 for j in range(blo, bhi):
2025-07-02 04:52:33.447 bj = b[j]
2025-07-02 04:52:33.447 cruncher.set_seq2(bj)
2025-07-02 04:52:33.447 for i in range(alo, ahi):
2025-07-02 04:52:33.447 ai = a[i]
2025-07-02 04:52:33.447 if ai == bj:
2025-07-02 04:52:33.447 if eqi is None:
2025-07-02 04:52:33.447 eqi, eqj = i, j
2025-07-02 04:52:33.447 continue
2025-07-02 04:52:33.447 cruncher.set_seq1(ai)
2025-07-02 04:52:33.447 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.447 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.447 # compares by a factor of 3.
2025-07-02 04:52:33.447 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.447 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.448 # of the computation is cached by cruncher
2025-07-02 04:52:33.448 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.448 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.448 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.448 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.448 if best_ratio < cutoff:
2025-07-02 04:52:33.448 # no non-identical "pretty close" pair
2025-07-02 04:52:33.448 if eqi is None:
2025-07-02 04:52:33.448 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.448 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.448 return
2025-07-02 04:52:33.448 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.448 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.448 else:
2025-07-02 04:52:33.448 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.448 eqi = None
2025-07-02 04:52:33.448
2025-07-02 04:52:33.448 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.448 # identical
2025-07-02 04:52:33.448
2025-07-02 04:52:33.449 # pump out diffs from before the synch point
2025-07-02 04:52:33.449 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.449
2025-07-02 04:52:33.449 # do intraline marking on the synch pair
2025-07-02 04:52:33.449 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.449 if eqi is None:
2025-07-02 04:52:33.449 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.449 atags = btags = ""
2025-07-02 04:52:33.449 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.449 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.449 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.449 if tag == 'replace':
2025-07-02 04:52:33.449 atags += '^' * la
2025-07-02 04:52:33.449 btags += '^' * lb
2025-07-02 04:52:33.449 elif tag == 'delete':
2025-07-02 04:52:33.449 atags += '-' * la
2025-07-02 04:52:33.449 elif tag == 'insert':
2025-07-02 04:52:33.449 btags += '+' * lb
2025-07-02 04:52:33.449 elif tag == 'equal':
2025-07-02 04:52:33.449 atags += ' ' * la
2025-07-02 04:52:33.449 btags += ' ' * lb
2025-07-02 04:52:33.450 else:
2025-07-02 04:52:33.450 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.450 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.450 else:
2025-07-02 04:52:33.450 # the synch pair is identical
2025-07-02 04:52:33.450 yield ' ' + aelt
2025-07-02 04:52:33.450
2025-07-02 04:52:33.450 # pump out diffs from after the synch point
2025-07-02 04:52:33.450 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.450
2025-07-02 04:52:33.450 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.450 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.450
2025-07-02 04:52:33.450 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.450 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.450 alo = 409, ahi = 1101
2025-07-02 04:52:33.450 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.450 blo = 409, bhi = 1101
2025-07-02 04:52:33.450
2025-07-02 04:52:33.450 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.451 g = []
2025-07-02 04:52:33.451 if alo < ahi:
2025-07-02 04:52:33.451 if blo < bhi:
2025-07-02 04:52:33.451 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.451 else:
2025-07-02 04:52:33.451 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.451 elif blo < bhi:
2025-07-02 04:52:33.451 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.451
2025-07-02 04:52:33.451 > yield from g
2025-07-02 04:52:33.451
2025-07-02 04:52:33.451 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.451 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.451
2025-07-02 04:52:33.451 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.451 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.451 alo = 409, ahi = 1101
2025-07-02 04:52:33.451 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.451 blo = 409, bhi = 1101
2025-07-02 04:52:33.451
2025-07-02 04:52:33.451 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.452 r"""
2025-07-02 04:52:33.452 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.452 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.452 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.452 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.452
2025-07-02 04:52:33.452 Example:
2025-07-02 04:52:33.452
2025-07-02 04:52:33.452 >>> d = Differ()
2025-07-02 04:52:33.452 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.452 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.452 >>> print(''.join(results), end="")
2025-07-02 04:52:33.452 - abcDefghiJkl
2025-07-02 04:52:33.452 + abcdefGhijkl
2025-07-02 04:52:33.452 """
2025-07-02 04:52:33.452
2025-07-02 04:52:33.452 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.452 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.453 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.453 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.453 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.453
2025-07-02 04:52:33.453 # search for the pair that matches best without being identical
2025-07-02 04:52:33.453 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.453 # on junk -- unless we have to)
2025-07-02 04:52:33.453 for j in range(blo, bhi):
2025-07-02 04:52:33.453 bj = b[j]
2025-07-02 04:52:33.453 cruncher.set_seq2(bj)
2025-07-02 04:52:33.453 for i in range(alo, ahi):
2025-07-02 04:52:33.453 ai = a[i]
2025-07-02 04:52:33.453 if ai == bj:
2025-07-02 04:52:33.453 if eqi is None:
2025-07-02 04:52:33.453 eqi, eqj = i, j
2025-07-02 04:52:33.453 continue
2025-07-02 04:52:33.453 cruncher.set_seq1(ai)
2025-07-02 04:52:33.453 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.453 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.453 # compares by a factor of 3.
2025-07-02 04:52:33.453 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.454 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.454 # of the computation is cached by cruncher
2025-07-02 04:52:33.454 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.454 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.454 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.454 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.454 if best_ratio < cutoff:
2025-07-02 04:52:33.454 # no non-identical "pretty close" pair
2025-07-02 04:52:33.454 if eqi is None:
2025-07-02 04:52:33.454 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.454 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.454 return
2025-07-02 04:52:33.454 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.454 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.454 else:
2025-07-02 04:52:33.454 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.454 eqi = None
2025-07-02 04:52:33.454
2025-07-02 04:52:33.454 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.454 # identical
2025-07-02 04:52:33.455
2025-07-02 04:52:33.455 # pump out diffs from before the synch point
2025-07-02 04:52:33.455 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.455
2025-07-02 04:52:33.455 # do intraline marking on the synch pair
2025-07-02 04:52:33.455 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.455 if eqi is None:
2025-07-02 04:52:33.455 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.455 atags = btags = ""
2025-07-02 04:52:33.455 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.455 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.455 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.455 if tag == 'replace':
2025-07-02 04:52:33.455 atags += '^' * la
2025-07-02 04:52:33.455 btags += '^' * lb
2025-07-02 04:52:33.455 elif tag == 'delete':
2025-07-02 04:52:33.455 atags += '-' * la
2025-07-02 04:52:33.455 elif tag == 'insert':
2025-07-02 04:52:33.455 btags += '+' * lb
2025-07-02 04:52:33.455 elif tag == 'equal':
2025-07-02 04:52:33.455 atags += ' ' * la
2025-07-02 04:52:33.456 btags += ' ' * lb
2025-07-02 04:52:33.456 else:
2025-07-02 04:52:33.456 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.456 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.456 else:
2025-07-02 04:52:33.456 # the synch pair is identical
2025-07-02 04:52:33.456 yield ' ' + aelt
2025-07-02 04:52:33.456
2025-07-02 04:52:33.456 # pump out diffs from after the synch point
2025-07-02 04:52:33.456 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.456
2025-07-02 04:52:33.456 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.456 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.456
2025-07-02 04:52:33.456 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.456 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.456 alo = 410, ahi = 1101
2025-07-02 04:52:33.456 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.456 blo = 410, bhi = 1101
2025-07-02 04:52:33.456
2025-07-02 04:52:33.457 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.457 g = []
2025-07-02 04:52:33.457 if alo < ahi:
2025-07-02 04:52:33.457 if blo < bhi:
2025-07-02 04:52:33.457 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.457 else:
2025-07-02 04:52:33.457 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.457 elif blo < bhi:
2025-07-02 04:52:33.457 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.457
2025-07-02 04:52:33.457 > yield from g
2025-07-02 04:52:33.457
2025-07-02 04:52:33.457 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.457 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.457
2025-07-02 04:52:33.457 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.457 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.457 alo = 410, ahi = 1101
2025-07-02 04:52:33.457 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.457 blo = 410, bhi = 1101
2025-07-02 04:52:33.457
2025-07-02 04:52:33.458 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.458 r"""
2025-07-02 04:52:33.458 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.458 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.458 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.458 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.458
2025-07-02 04:52:33.458 Example:
2025-07-02 04:52:33.458
2025-07-02 04:52:33.458 >>> d = Differ()
2025-07-02 04:52:33.458 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.458 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.458 >>> print(''.join(results), end="")
2025-07-02 04:52:33.458 - abcDefghiJkl
2025-07-02 04:52:33.458 + abcdefGhijkl
2025-07-02 04:52:33.458 """
2025-07-02 04:52:33.458
2025-07-02 04:52:33.458 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.459 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.459 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.459 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.459 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.459
2025-07-02 04:52:33.459 # search for the pair that matches best without being identical
2025-07-02 04:52:33.459 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.459 # on junk -- unless we have to)
2025-07-02 04:52:33.459 for j in range(blo, bhi):
2025-07-02 04:52:33.459 bj = b[j]
2025-07-02 04:52:33.459 cruncher.set_seq2(bj)
2025-07-02 04:52:33.459 for i in range(alo, ahi):
2025-07-02 04:52:33.459 ai = a[i]
2025-07-02 04:52:33.459 if ai == bj:
2025-07-02 04:52:33.459 if eqi is None:
2025-07-02 04:52:33.459 eqi, eqj = i, j
2025-07-02 04:52:33.459 continue
2025-07-02 04:52:33.459 cruncher.set_seq1(ai)
2025-07-02 04:52:33.459 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.459 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.459 # compares by a factor of 3.
2025-07-02 04:52:33.460 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.460 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.460 # of the computation is cached by cruncher
2025-07-02 04:52:33.460 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.460 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.460 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.460 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.460 if best_ratio < cutoff:
2025-07-02 04:52:33.460 # no non-identical "pretty close" pair
2025-07-02 04:52:33.460 if eqi is None:
2025-07-02 04:52:33.460 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.460 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.460 return
2025-07-02 04:52:33.460 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.460 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.460 else:
2025-07-02 04:52:33.460 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.460 eqi = None
2025-07-02 04:52:33.460
2025-07-02 04:52:33.460 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.461 # identical
2025-07-02 04:52:33.461
2025-07-02 04:52:33.461 # pump out diffs from before the synch point
2025-07-02 04:52:33.461 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.461
2025-07-02 04:52:33.461 # do intraline marking on the synch pair
2025-07-02 04:52:33.461 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.461 if eqi is None:
2025-07-02 04:52:33.461 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.461 atags = btags = ""
2025-07-02 04:52:33.461 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.461 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.461 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.461 if tag == 'replace':
2025-07-02 04:52:33.461 atags += '^' * la
2025-07-02 04:52:33.461 btags += '^' * lb
2025-07-02 04:52:33.461 elif tag == 'delete':
2025-07-02 04:52:33.461 atags += '-' * la
2025-07-02 04:52:33.461 elif tag == 'insert':
2025-07-02 04:52:33.461 btags += '+' * lb
2025-07-02 04:52:33.461 elif tag == 'equal':
2025-07-02 04:52:33.462 atags += ' ' * la
2025-07-02 04:52:33.462 btags += ' ' * lb
2025-07-02 04:52:33.462 else:
2025-07-02 04:52:33.462 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.462 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.462 else:
2025-07-02 04:52:33.462 # the synch pair is identical
2025-07-02 04:52:33.462 yield ' ' + aelt
2025-07-02 04:52:33.462
2025-07-02 04:52:33.462 # pump out diffs from after the synch point
2025-07-02 04:52:33.462 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.462
2025-07-02 04:52:33.462 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.462 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.462
2025-07-02 04:52:33.462 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.462 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.462 alo = 411, ahi = 1101
2025-07-02 04:52:33.462 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.462 blo = 411, bhi = 1101
2025-07-02 04:52:33.463
2025-07-02 04:52:33.463 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.463 g = []
2025-07-02 04:52:33.463 if alo < ahi:
2025-07-02 04:52:33.463 if blo < bhi:
2025-07-02 04:52:33.463 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.463 else:
2025-07-02 04:52:33.463 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.463 elif blo < bhi:
2025-07-02 04:52:33.463 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.463
2025-07-02 04:52:33.463 > yield from g
2025-07-02 04:52:33.463
2025-07-02 04:52:33.463 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.463 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.463
2025-07-02 04:52:33.463 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.463 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.463 alo = 411, ahi = 1101
2025-07-02 04:52:33.463 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.464 blo = 411, bhi = 1101
2025-07-02 04:52:33.464
2025-07-02 04:52:33.464 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.464 r"""
2025-07-02 04:52:33.464 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.464 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.464 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.464 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.464
2025-07-02 04:52:33.464 Example:
2025-07-02 04:52:33.464
2025-07-02 04:52:33.464 >>> d = Differ()
2025-07-02 04:52:33.464 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.464 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.464 >>> print(''.join(results), end="")
2025-07-02 04:52:33.464 - abcDefghiJkl
2025-07-02 04:52:33.464 + abcdefGhijkl
2025-07-02 04:52:33.464 """
2025-07-02 04:52:33.464
2025-07-02 04:52:33.465 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.465 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.465 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.465 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.465 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.465
2025-07-02 04:52:33.465 # search for the pair that matches best without being identical
2025-07-02 04:52:33.465 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.465 # on junk -- unless we have to)
2025-07-02 04:52:33.465 for j in range(blo, bhi):
2025-07-02 04:52:33.465 bj = b[j]
2025-07-02 04:52:33.465 cruncher.set_seq2(bj)
2025-07-02 04:52:33.465 for i in range(alo, ahi):
2025-07-02 04:52:33.465 ai = a[i]
2025-07-02 04:52:33.465 if ai == bj:
2025-07-02 04:52:33.465 if eqi is None:
2025-07-02 04:52:33.465 eqi, eqj = i, j
2025-07-02 04:52:33.465 continue
2025-07-02 04:52:33.465 cruncher.set_seq1(ai)
2025-07-02 04:52:33.465 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.466 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.466 # compares by a factor of 3.
2025-07-02 04:52:33.466 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.466 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.466 # of the computation is cached by cruncher
2025-07-02 04:52:33.466 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.466 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.466 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.466 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.466 if best_ratio < cutoff:
2025-07-02 04:52:33.466 # no non-identical "pretty close" pair
2025-07-02 04:52:33.466 if eqi is None:
2025-07-02 04:52:33.466 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.466 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.466 return
2025-07-02 04:52:33.466 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.466 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.466 else:
2025-07-02 04:52:33.466 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.466 eqi = None
2025-07-02 04:52:33.466
2025-07-02 04:52:33.467 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.467 # identical
2025-07-02 04:52:33.467
2025-07-02 04:52:33.467 # pump out diffs from before the synch point
2025-07-02 04:52:33.467 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.467
2025-07-02 04:52:33.467 # do intraline marking on the synch pair
2025-07-02 04:52:33.467 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.467 if eqi is None:
2025-07-02 04:52:33.467 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.467 atags = btags = ""
2025-07-02 04:52:33.467 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.467 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.467 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.467 if tag == 'replace':
2025-07-02 04:52:33.467 atags += '^' * la
2025-07-02 04:52:33.467 btags += '^' * lb
2025-07-02 04:52:33.467 elif tag == 'delete':
2025-07-02 04:52:33.467 atags += '-' * la
2025-07-02 04:52:33.467 elif tag == 'insert':
2025-07-02 04:52:33.468 btags += '+' * lb
2025-07-02 04:52:33.468 elif tag == 'equal':
2025-07-02 04:52:33.468 atags += ' ' * la
2025-07-02 04:52:33.468 btags += ' ' * lb
2025-07-02 04:52:33.468 else:
2025-07-02 04:52:33.468 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.468 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.468 else:
2025-07-02 04:52:33.468 # the synch pair is identical
2025-07-02 04:52:33.468 yield ' ' + aelt
2025-07-02 04:52:33.468
2025-07-02 04:52:33.468 # pump out diffs from after the synch point
2025-07-02 04:52:33.468 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.468
2025-07-02 04:52:33.468 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.468 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.468
2025-07-02 04:52:33.468 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.468 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.468 alo = 412, ahi = 1101
2025-07-02 04:52:33.468 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.469 blo = 412, bhi = 1101
2025-07-02 04:52:33.469
2025-07-02 04:52:33.469 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.469 g = []
2025-07-02 04:52:33.469 if alo < ahi:
2025-07-02 04:52:33.469 if blo < bhi:
2025-07-02 04:52:33.469 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.469 else:
2025-07-02 04:52:33.469 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.469 elif blo < bhi:
2025-07-02 04:52:33.469 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.469
2025-07-02 04:52:33.469 > yield from g
2025-07-02 04:52:33.469
2025-07-02 04:52:33.469 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.469 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.469
2025-07-02 04:52:33.469 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.469 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.469 alo = 412, ahi = 1101
2025-07-02 04:52:33.469 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.470 blo = 412, bhi = 1101
2025-07-02 04:52:33.470
2025-07-02 04:52:33.470 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.470 r"""
2025-07-02 04:52:33.470 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.470 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.470 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.470 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.470
2025-07-02 04:52:33.470 Example:
2025-07-02 04:52:33.470
2025-07-02 04:52:33.470 >>> d = Differ()
2025-07-02 04:52:33.470 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.470 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.470 >>> print(''.join(results), end="")
2025-07-02 04:52:33.470 - abcDefghiJkl
2025-07-02 04:52:33.470 + abcdefGhijkl
2025-07-02 04:52:33.470 """
2025-07-02 04:52:33.471
2025-07-02 04:52:33.471 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.471 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.471 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.471 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.471 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.471
2025-07-02 04:52:33.471 # search for the pair that matches best without being identical
2025-07-02 04:52:33.471 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.471 # on junk -- unless we have to)
2025-07-02 04:52:33.471 for j in range(blo, bhi):
2025-07-02 04:52:33.471 bj = b[j]
2025-07-02 04:52:33.471 cruncher.set_seq2(bj)
2025-07-02 04:52:33.471 for i in range(alo, ahi):
2025-07-02 04:52:33.471 ai = a[i]
2025-07-02 04:52:33.471 if ai == bj:
2025-07-02 04:52:33.471 if eqi is None:
2025-07-02 04:52:33.471 eqi, eqj = i, j
2025-07-02 04:52:33.471 continue
2025-07-02 04:52:33.471 cruncher.set_seq1(ai)
2025-07-02 04:52:33.471 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.472 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.472 # compares by a factor of 3.
2025-07-02 04:52:33.472 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.472 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.472 # of the computation is cached by cruncher
2025-07-02 04:52:33.472 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.472 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.472 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.472 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.472 if best_ratio < cutoff:
2025-07-02 04:52:33.472 # no non-identical "pretty close" pair
2025-07-02 04:52:33.472 if eqi is None:
2025-07-02 04:52:33.472 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.472 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.472 return
2025-07-02 04:52:33.472 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.472 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.472 else:
2025-07-02 04:52:33.472 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.472 eqi = None
2025-07-02 04:52:33.473
2025-07-02 04:52:33.473 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.473 # identical
2025-07-02 04:52:33.473
2025-07-02 04:52:33.473 # pump out diffs from before the synch point
2025-07-02 04:52:33.473 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.473
2025-07-02 04:52:33.473 # do intraline marking on the synch pair
2025-07-02 04:52:33.473 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.473 if eqi is None:
2025-07-02 04:52:33.473 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.473 atags = btags = ""
2025-07-02 04:52:33.473 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.473 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.473 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.473 if tag == 'replace':
2025-07-02 04:52:33.473 atags += '^' * la
2025-07-02 04:52:33.473 btags += '^' * lb
2025-07-02 04:52:33.473 elif tag == 'delete':
2025-07-02 04:52:33.473 atags += '-' * la
2025-07-02 04:52:33.473 elif tag == 'insert':
2025-07-02 04:52:33.474 btags += '+' * lb
2025-07-02 04:52:33.474 elif tag == 'equal':
2025-07-02 04:52:33.474 atags += ' ' * la
2025-07-02 04:52:33.474 btags += ' ' * lb
2025-07-02 04:52:33.474 else:
2025-07-02 04:52:33.474 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.474 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.474 else:
2025-07-02 04:52:33.474 # the synch pair is identical
2025-07-02 04:52:33.474 yield ' ' + aelt
2025-07-02 04:52:33.474
2025-07-02 04:52:33.474 # pump out diffs from after the synch point
2025-07-02 04:52:33.474 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.474
2025-07-02 04:52:33.474 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.474 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.474
2025-07-02 04:52:33.474 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.474 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.474 alo = 413, ahi = 1101
2025-07-02 04:52:33.475 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.475 blo = 413, bhi = 1101
2025-07-02 04:52:33.475
2025-07-02 04:52:33.475 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.475 g = []
2025-07-02 04:52:33.475 if alo < ahi:
2025-07-02 04:52:33.475 if blo < bhi:
2025-07-02 04:52:33.475 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.475 else:
2025-07-02 04:52:33.475 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.475 elif blo < bhi:
2025-07-02 04:52:33.475 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.475
2025-07-02 04:52:33.475 > yield from g
2025-07-02 04:52:33.475
2025-07-02 04:52:33.475 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.475 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.475
2025-07-02 04:52:33.475 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.475 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.475 alo = 413, ahi = 1101
2025-07-02 04:52:33.476 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.476 blo = 413, bhi = 1101
2025-07-02 04:52:33.476
2025-07-02 04:52:33.476 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.476 r"""
2025-07-02 04:52:33.476 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.476 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.476 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.476 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.476
2025-07-02 04:52:33.476 Example:
2025-07-02 04:52:33.476
2025-07-02 04:52:33.476 >>> d = Differ()
2025-07-02 04:52:33.476 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.476 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.476 >>> print(''.join(results), end="")
2025-07-02 04:52:33.476 - abcDefghiJkl
2025-07-02 04:52:33.476 + abcdefGhijkl
2025-07-02 04:52:33.477 """
2025-07-02 04:52:33.477
2025-07-02 04:52:33.477 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.477 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.477 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.477 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.477 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.477
2025-07-02 04:52:33.477 # search for the pair that matches best without being identical
2025-07-02 04:52:33.477 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.477 # on junk -- unless we have to)
2025-07-02 04:52:33.477 for j in range(blo, bhi):
2025-07-02 04:52:33.477 bj = b[j]
2025-07-02 04:52:33.477 cruncher.set_seq2(bj)
2025-07-02 04:52:33.477 for i in range(alo, ahi):
2025-07-02 04:52:33.477 ai = a[i]
2025-07-02 04:52:33.477 if ai == bj:
2025-07-02 04:52:33.477 if eqi is None:
2025-07-02 04:52:33.477 eqi, eqj = i, j
2025-07-02 04:52:33.477 continue
2025-07-02 04:52:33.477 cruncher.set_seq1(ai)
2025-07-02 04:52:33.478 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.478 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.478 # compares by a factor of 3.
2025-07-02 04:52:33.478 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.478 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.478 # of the computation is cached by cruncher
2025-07-02 04:52:33.478 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.478 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.478 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.478 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.478 if best_ratio < cutoff:
2025-07-02 04:52:33.478 # no non-identical "pretty close" pair
2025-07-02 04:52:33.478 if eqi is None:
2025-07-02 04:52:33.478 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.478 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.478 return
2025-07-02 04:52:33.478 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.478 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.478 else:
2025-07-02 04:52:33.478 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.479 eqi = None
2025-07-02 04:52:33.479
2025-07-02 04:52:33.479 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.479 # identical
2025-07-02 04:52:33.479
2025-07-02 04:52:33.479 # pump out diffs from before the synch point
2025-07-02 04:52:33.479 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.479
2025-07-02 04:52:33.479 # do intraline marking on the synch pair
2025-07-02 04:52:33.479 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.479 if eqi is None:
2025-07-02 04:52:33.479 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.479 atags = btags = ""
2025-07-02 04:52:33.479 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.479 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.479 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.479 if tag == 'replace':
2025-07-02 04:52:33.479 atags += '^' * la
2025-07-02 04:52:33.479 btags += '^' * lb
2025-07-02 04:52:33.479 elif tag == 'delete':
2025-07-02 04:52:33.479 atags += '-' * la
2025-07-02 04:52:33.480 elif tag == 'insert':
2025-07-02 04:52:33.480 btags += '+' * lb
2025-07-02 04:52:33.480 elif tag == 'equal':
2025-07-02 04:52:33.480 atags += ' ' * la
2025-07-02 04:52:33.480 btags += ' ' * lb
2025-07-02 04:52:33.480 else:
2025-07-02 04:52:33.480 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.480 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.480 else:
2025-07-02 04:52:33.480 # the synch pair is identical
2025-07-02 04:52:33.480 yield ' ' + aelt
2025-07-02 04:52:33.480
2025-07-02 04:52:33.480 # pump out diffs from after the synch point
2025-07-02 04:52:33.480 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.480
2025-07-02 04:52:33.480 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.480 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.480
2025-07-02 04:52:33.480 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.480 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.481 alo = 414, ahi = 1101
2025-07-02 04:52:33.481 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.481 blo = 414, bhi = 1101
2025-07-02 04:52:33.481
2025-07-02 04:52:33.481 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.481 g = []
2025-07-02 04:52:33.481 if alo < ahi:
2025-07-02 04:52:33.481 if blo < bhi:
2025-07-02 04:52:33.481 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.481 else:
2025-07-02 04:52:33.481 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.481 elif blo < bhi:
2025-07-02 04:52:33.481 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.481
2025-07-02 04:52:33.481 > yield from g
2025-07-02 04:52:33.481
2025-07-02 04:52:33.481 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.481 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.481
2025-07-02 04:52:33.481 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.481 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.482 alo = 414, ahi = 1101
2025-07-02 04:52:33.482 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.482 blo = 414, bhi = 1101
2025-07-02 04:52:33.482
2025-07-02 04:52:33.482 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.482 r"""
2025-07-02 04:52:33.482 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.482 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.482 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.482 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.482
2025-07-02 04:52:33.482 Example:
2025-07-02 04:52:33.482
2025-07-02 04:52:33.482 >>> d = Differ()
2025-07-02 04:52:33.482 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.482 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.482 >>> print(''.join(results), end="")
2025-07-02 04:52:33.482 - abcDefghiJkl
2025-07-02 04:52:33.482 + abcdefGhijkl
2025-07-02 04:52:33.483 """
2025-07-02 04:52:33.483
2025-07-02 04:52:33.483 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.483 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.483 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.483 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.483 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.483
2025-07-02 04:52:33.483 # search for the pair that matches best without being identical
2025-07-02 04:52:33.483 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.483 # on junk -- unless we have to)
2025-07-02 04:52:33.483 for j in range(blo, bhi):
2025-07-02 04:52:33.483 bj = b[j]
2025-07-02 04:52:33.483 cruncher.set_seq2(bj)
2025-07-02 04:52:33.483 for i in range(alo, ahi):
2025-07-02 04:52:33.483 ai = a[i]
2025-07-02 04:52:33.483 if ai == bj:
2025-07-02 04:52:33.483 if eqi is None:
2025-07-02 04:52:33.483 eqi, eqj = i, j
2025-07-02 04:52:33.483 continue
2025-07-02 04:52:33.484 cruncher.set_seq1(ai)
2025-07-02 04:52:33.484 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.484 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.484 # compares by a factor of 3.
2025-07-02 04:52:33.484 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.484 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.484 # of the computation is cached by cruncher
2025-07-02 04:52:33.484 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.484 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.484 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.484 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.484 if best_ratio < cutoff:
2025-07-02 04:52:33.484 # no non-identical "pretty close" pair
2025-07-02 04:52:33.484 if eqi is None:
2025-07-02 04:52:33.484 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.484 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.484 return
2025-07-02 04:52:33.484 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.484 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.484 else:
2025-07-02 04:52:33.485 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.485 eqi = None
2025-07-02 04:52:33.485
2025-07-02 04:52:33.485 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.485 # identical
2025-07-02 04:52:33.485
2025-07-02 04:52:33.485 # pump out diffs from before the synch point
2025-07-02 04:52:33.485 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.485
2025-07-02 04:52:33.485 # do intraline marking on the synch pair
2025-07-02 04:52:33.485 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.485 if eqi is None:
2025-07-02 04:52:33.485 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.485 atags = btags = ""
2025-07-02 04:52:33.485 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.485 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.485 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.485 if tag == 'replace':
2025-07-02 04:52:33.485 atags += '^' * la
2025-07-02 04:52:33.485 btags += '^' * lb
2025-07-02 04:52:33.485 elif tag == 'delete':
2025-07-02 04:52:33.486 atags += '-' * la
2025-07-02 04:52:33.486 elif tag == 'insert':
2025-07-02 04:52:33.486 btags += '+' * lb
2025-07-02 04:52:33.486 elif tag == 'equal':
2025-07-02 04:52:33.486 atags += ' ' * la
2025-07-02 04:52:33.486 btags += ' ' * lb
2025-07-02 04:52:33.486 else:
2025-07-02 04:52:33.486 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.486 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.486 else:
2025-07-02 04:52:33.486 # the synch pair is identical
2025-07-02 04:52:33.486 yield ' ' + aelt
2025-07-02 04:52:33.486
2025-07-02 04:52:33.486 # pump out diffs from after the synch point
2025-07-02 04:52:33.486 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.486
2025-07-02 04:52:33.486 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.486 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.486
2025-07-02 04:52:33.486 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.486 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.487 alo = 415, ahi = 1101
2025-07-02 04:52:33.487 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.487 blo = 415, bhi = 1101
2025-07-02 04:52:33.487
2025-07-02 04:52:33.487 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.487 g = []
2025-07-02 04:52:33.487 if alo < ahi:
2025-07-02 04:52:33.487 if blo < bhi:
2025-07-02 04:52:33.487 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.487 else:
2025-07-02 04:52:33.487 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.487 elif blo < bhi:
2025-07-02 04:52:33.487 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.487
2025-07-02 04:52:33.487 > yield from g
2025-07-02 04:52:33.487
2025-07-02 04:52:33.487 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.487 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.487
2025-07-02 04:52:33.487 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.488 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.488 alo = 415, ahi = 1101
2025-07-02 04:52:33.488 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.488 blo = 415, bhi = 1101
2025-07-02 04:52:33.488
2025-07-02 04:52:33.488 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.488 r"""
2025-07-02 04:52:33.488 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.488 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.488 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.488 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.488
2025-07-02 04:52:33.488 Example:
2025-07-02 04:52:33.488
2025-07-02 04:52:33.488 >>> d = Differ()
2025-07-02 04:52:33.488 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.488 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.488 >>> print(''.join(results), end="")
2025-07-02 04:52:33.488 - abcDefghiJkl
2025-07-02 04:52:33.489 + abcdefGhijkl
2025-07-02 04:52:33.489 """
2025-07-02 04:52:33.489
2025-07-02 04:52:33.489 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.489 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.489 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.489 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.489 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.489
2025-07-02 04:52:33.489 # search for the pair that matches best without being identical
2025-07-02 04:52:33.489 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.489 # on junk -- unless we have to)
2025-07-02 04:52:33.489 for j in range(blo, bhi):
2025-07-02 04:52:33.489 bj = b[j]
2025-07-02 04:52:33.489 cruncher.set_seq2(bj)
2025-07-02 04:52:33.489 for i in range(alo, ahi):
2025-07-02 04:52:33.489 ai = a[i]
2025-07-02 04:52:33.489 if ai == bj:
2025-07-02 04:52:33.489 if eqi is None:
2025-07-02 04:52:33.489 eqi, eqj = i, j
2025-07-02 04:52:33.490 continue
2025-07-02 04:52:33.490 cruncher.set_seq1(ai)
2025-07-02 04:52:33.490 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.490 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.490 # compares by a factor of 3.
2025-07-02 04:52:33.490 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.490 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.490 # of the computation is cached by cruncher
2025-07-02 04:52:33.490 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.490 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.490 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.490 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.490 if best_ratio < cutoff:
2025-07-02 04:52:33.490 # no non-identical "pretty close" pair
2025-07-02 04:52:33.490 if eqi is None:
2025-07-02 04:52:33.490 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.490 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.490 return
2025-07-02 04:52:33.490 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.490 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.491 else:
2025-07-02 04:52:33.491 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.491 eqi = None
2025-07-02 04:52:33.491
2025-07-02 04:52:33.491 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.491 # identical
2025-07-02 04:52:33.491
2025-07-02 04:52:33.491 # pump out diffs from before the synch point
2025-07-02 04:52:33.491 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.491
2025-07-02 04:52:33.491 # do intraline marking on the synch pair
2025-07-02 04:52:33.491 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.491 if eqi is None:
2025-07-02 04:52:33.491 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.491 atags = btags = ""
2025-07-02 04:52:33.491 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.491 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.491 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.491 if tag == 'replace':
2025-07-02 04:52:33.491 atags += '^' * la
2025-07-02 04:52:33.491 btags += '^' * lb
2025-07-02 04:52:33.492 elif tag == 'delete':
2025-07-02 04:52:33.492 atags += '-' * la
2025-07-02 04:52:33.492 elif tag == 'insert':
2025-07-02 04:52:33.492 btags += '+' * lb
2025-07-02 04:52:33.492 elif tag == 'equal':
2025-07-02 04:52:33.492 atags += ' ' * la
2025-07-02 04:52:33.492 btags += ' ' * lb
2025-07-02 04:52:33.492 else:
2025-07-02 04:52:33.492 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.492 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.492 else:
2025-07-02 04:52:33.492 # the synch pair is identical
2025-07-02 04:52:33.492 yield ' ' + aelt
2025-07-02 04:52:33.492
2025-07-02 04:52:33.492 # pump out diffs from after the synch point
2025-07-02 04:52:33.492 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.492
2025-07-02 04:52:33.492 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.492 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.492
2025-07-02 04:52:33.493 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.493 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.493 alo = 416, ahi = 1101
2025-07-02 04:52:33.493 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.493 blo = 416, bhi = 1101
2025-07-02 04:52:33.493
2025-07-02 04:52:33.493 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.493 g = []
2025-07-02 04:52:33.493 if alo < ahi:
2025-07-02 04:52:33.493 if blo < bhi:
2025-07-02 04:52:33.493 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.493 else:
2025-07-02 04:52:33.493 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.493 elif blo < bhi:
2025-07-02 04:52:33.493 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.493
2025-07-02 04:52:33.493 > yield from g
2025-07-02 04:52:33.493
2025-07-02 04:52:33.493 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.493 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.493
2025-07-02 04:52:33.494 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.494 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.494 alo = 416, ahi = 1101
2025-07-02 04:52:33.494 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.494 blo = 416, bhi = 1101
2025-07-02 04:52:33.494
2025-07-02 04:52:33.494 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.494 r"""
2025-07-02 04:52:33.494 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.494 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.494 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.494 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.494
2025-07-02 04:52:33.494 Example:
2025-07-02 04:52:33.494
2025-07-02 04:52:33.494 >>> d = Differ()
2025-07-02 04:52:33.494 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.494 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.494 >>> print(''.join(results), end="")
2025-07-02 04:52:33.494 - abcDefghiJkl
2025-07-02 04:52:33.495 + abcdefGhijkl
2025-07-02 04:52:33.495 """
2025-07-02 04:52:33.495
2025-07-02 04:52:33.495 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.495 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.495 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.495 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.495 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.495
2025-07-02 04:52:33.495 # search for the pair that matches best without being identical
2025-07-02 04:52:33.495 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.495 # on junk -- unless we have to)
2025-07-02 04:52:33.495 for j in range(blo, bhi):
2025-07-02 04:52:33.495 bj = b[j]
2025-07-02 04:52:33.495 cruncher.set_seq2(bj)
2025-07-02 04:52:33.495 for i in range(alo, ahi):
2025-07-02 04:52:33.495 ai = a[i]
2025-07-02 04:52:33.495 if ai == bj:
2025-07-02 04:52:33.495 if eqi is None:
2025-07-02 04:52:33.496 eqi, eqj = i, j
2025-07-02 04:52:33.496 continue
2025-07-02 04:52:33.496 cruncher.set_seq1(ai)
2025-07-02 04:52:33.496 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.496 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.496 # compares by a factor of 3.
2025-07-02 04:52:33.496 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.496 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.496 # of the computation is cached by cruncher
2025-07-02 04:52:33.496 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.496 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.496 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.496 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.496 if best_ratio < cutoff:
2025-07-02 04:52:33.496 # no non-identical "pretty close" pair
2025-07-02 04:52:33.496 if eqi is None:
2025-07-02 04:52:33.496 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.496 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.496 return
2025-07-02 04:52:33.496 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.497 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.497 else:
2025-07-02 04:52:33.497 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.497 eqi = None
2025-07-02 04:52:33.497
2025-07-02 04:52:33.497 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.497 # identical
2025-07-02 04:52:33.497
2025-07-02 04:52:33.497 # pump out diffs from before the synch point
2025-07-02 04:52:33.497 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.497
2025-07-02 04:52:33.497 # do intraline marking on the synch pair
2025-07-02 04:52:33.497 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.497 if eqi is None:
2025-07-02 04:52:33.497 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.497 atags = btags = ""
2025-07-02 04:52:33.497 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.497 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.497 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.497 if tag == 'replace':
2025-07-02 04:52:33.498 atags += '^' * la
2025-07-02 04:52:33.498 btags += '^' * lb
2025-07-02 04:52:33.498 elif tag == 'delete':
2025-07-02 04:52:33.498 atags += '-' * la
2025-07-02 04:52:33.498 elif tag == 'insert':
2025-07-02 04:52:33.498 btags += '+' * lb
2025-07-02 04:52:33.498 elif tag == 'equal':
2025-07-02 04:52:33.498 atags += ' ' * la
2025-07-02 04:52:33.498 btags += ' ' * lb
2025-07-02 04:52:33.498 else:
2025-07-02 04:52:33.498 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.498 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.498 else:
2025-07-02 04:52:33.498 # the synch pair is identical
2025-07-02 04:52:33.498 yield ' ' + aelt
2025-07-02 04:52:33.498
2025-07-02 04:52:33.498 # pump out diffs from after the synch point
2025-07-02 04:52:33.498 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.498
2025-07-02 04:52:33.498 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.498 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.499
2025-07-02 04:52:33.499 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.499 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.499 alo = 417, ahi = 1101
2025-07-02 04:52:33.499 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.499 blo = 417, bhi = 1101
2025-07-02 04:52:33.499
2025-07-02 04:52:33.499 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.499 g = []
2025-07-02 04:52:33.499 if alo < ahi:
2025-07-02 04:52:33.499 if blo < bhi:
2025-07-02 04:52:33.499 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.499 else:
2025-07-02 04:52:33.499 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.499 elif blo < bhi:
2025-07-02 04:52:33.499 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.499
2025-07-02 04:52:33.499 > yield from g
2025-07-02 04:52:33.499
2025-07-02 04:52:33.499 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.499 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.500
2025-07-02 04:52:33.500 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.500 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.500 alo = 417, ahi = 1101
2025-07-02 04:52:33.500 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.500 blo = 417, bhi = 1101
2025-07-02 04:52:33.500
2025-07-02 04:52:33.500 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.500 r"""
2025-07-02 04:52:33.500 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.500 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.500 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.500 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.500
2025-07-02 04:52:33.500 Example:
2025-07-02 04:52:33.500
2025-07-02 04:52:33.500 >>> d = Differ()
2025-07-02 04:52:33.500 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.500 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.500 >>> print(''.join(results), end="")
2025-07-02 04:52:33.500 - abcDefghiJkl
2025-07-02 04:52:33.501 + abcdefGhijkl
2025-07-02 04:52:33.501 """
2025-07-02 04:52:33.501
2025-07-02 04:52:33.501 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.501 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.501 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.501 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.501 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.501
2025-07-02 04:52:33.501 # search for the pair that matches best without being identical
2025-07-02 04:52:33.501 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.501 # on junk -- unless we have to)
2025-07-02 04:52:33.501 for j in range(blo, bhi):
2025-07-02 04:52:33.501 bj = b[j]
2025-07-02 04:52:33.501 cruncher.set_seq2(bj)
2025-07-02 04:52:33.501 for i in range(alo, ahi):
2025-07-02 04:52:33.501 ai = a[i]
2025-07-02 04:52:33.501 if ai == bj:
2025-07-02 04:52:33.501 if eqi is None:
2025-07-02 04:52:33.501 eqi, eqj = i, j
2025-07-02 04:52:33.502 continue
2025-07-02 04:52:33.502 cruncher.set_seq1(ai)
2025-07-02 04:52:33.502 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.502 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.502 # compares by a factor of 3.
2025-07-02 04:52:33.502 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.502 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.502 # of the computation is cached by cruncher
2025-07-02 04:52:33.502 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.502 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.502 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.502 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.502 if best_ratio < cutoff:
2025-07-02 04:52:33.502 # no non-identical "pretty close" pair
2025-07-02 04:52:33.502 if eqi is None:
2025-07-02 04:52:33.502 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.502 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.502 return
2025-07-02 04:52:33.502 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.502 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.502 else:
2025-07-02 04:52:33.503 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.503 eqi = None
2025-07-02 04:52:33.503
2025-07-02 04:52:33.503 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.503 # identical
2025-07-02 04:52:33.503
2025-07-02 04:52:33.503 # pump out diffs from before the synch point
2025-07-02 04:52:33.503 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.503
2025-07-02 04:52:33.503 # do intraline marking on the synch pair
2025-07-02 04:52:33.503 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.503 if eqi is None:
2025-07-02 04:52:33.503 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.503 atags = btags = ""
2025-07-02 04:52:33.503 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.503 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.503 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.503 if tag == 'replace':
2025-07-02 04:52:33.503 atags += '^' * la
2025-07-02 04:52:33.503 btags += '^' * lb
2025-07-02 04:52:33.503 elif tag == 'delete':
2025-07-02 04:52:33.503 atags += '-' * la
2025-07-02 04:52:33.504 elif tag == 'insert':
2025-07-02 04:52:33.504 btags += '+' * lb
2025-07-02 04:52:33.504 elif tag == 'equal':
2025-07-02 04:52:33.504 atags += ' ' * la
2025-07-02 04:52:33.504 btags += ' ' * lb
2025-07-02 04:52:33.504 else:
2025-07-02 04:52:33.504 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.504 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.504 else:
2025-07-02 04:52:33.504 # the synch pair is identical
2025-07-02 04:52:33.504 yield ' ' + aelt
2025-07-02 04:52:33.504
2025-07-02 04:52:33.504 # pump out diffs from after the synch point
2025-07-02 04:52:33.504 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.504
2025-07-02 04:52:33.504 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.504 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.504
2025-07-02 04:52:33.504 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.504 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.504 alo = 418, ahi = 1101
2025-07-02 04:52:33.505 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.505 blo = 418, bhi = 1101
2025-07-02 04:52:33.505
2025-07-02 04:52:33.505 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.505 g = []
2025-07-02 04:52:33.505 if alo < ahi:
2025-07-02 04:52:33.505 if blo < bhi:
2025-07-02 04:52:33.505 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.505 else:
2025-07-02 04:52:33.505 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.505 elif blo < bhi:
2025-07-02 04:52:33.505 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.505
2025-07-02 04:52:33.505 > yield from g
2025-07-02 04:52:33.505
2025-07-02 04:52:33.505 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.505 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.505
2025-07-02 04:52:33.505 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.506 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.506 alo = 418, ahi = 1101
2025-07-02 04:52:33.506 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.506 blo = 418, bhi = 1101
2025-07-02 04:52:33.506
2025-07-02 04:52:33.506 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.506 r"""
2025-07-02 04:52:33.506 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.506 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.506 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.506 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.506
2025-07-02 04:52:33.506 Example:
2025-07-02 04:52:33.506
2025-07-02 04:52:33.506 >>> d = Differ()
2025-07-02 04:52:33.506 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.506 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.506 >>> print(''.join(results), end="")
2025-07-02 04:52:33.506 - abcDefghiJkl
2025-07-02 04:52:33.507 + abcdefGhijkl
2025-07-02 04:52:33.507 """
2025-07-02 04:52:33.507
2025-07-02 04:52:33.507 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.507 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.507 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.507 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.507 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.507
2025-07-02 04:52:33.507 # search for the pair that matches best without being identical
2025-07-02 04:52:33.507 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.507 # on junk -- unless we have to)
2025-07-02 04:52:33.507 for j in range(blo, bhi):
2025-07-02 04:52:33.507 bj = b[j]
2025-07-02 04:52:33.507 cruncher.set_seq2(bj)
2025-07-02 04:52:33.507 for i in range(alo, ahi):
2025-07-02 04:52:33.507 ai = a[i]
2025-07-02 04:52:33.507 if ai == bj:
2025-07-02 04:52:33.507 if eqi is None:
2025-07-02 04:52:33.508 eqi, eqj = i, j
2025-07-02 04:52:33.508 continue
2025-07-02 04:52:33.508 cruncher.set_seq1(ai)
2025-07-02 04:52:33.508 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.508 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.508 # compares by a factor of 3.
2025-07-02 04:52:33.508 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.508 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.508 # of the computation is cached by cruncher
2025-07-02 04:52:33.508 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.508 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.508 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.508 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.508 if best_ratio < cutoff:
2025-07-02 04:52:33.508 # no non-identical "pretty close" pair
2025-07-02 04:52:33.508 if eqi is None:
2025-07-02 04:52:33.508 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.508 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.508 return
2025-07-02 04:52:33.508 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.508 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.509 else:
2025-07-02 04:52:33.509 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.509 eqi = None
2025-07-02 04:52:33.509
2025-07-02 04:52:33.509 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.509 # identical
2025-07-02 04:52:33.509
2025-07-02 04:52:33.509 # pump out diffs from before the synch point
2025-07-02 04:52:33.509 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.509
2025-07-02 04:52:33.509 # do intraline marking on the synch pair
2025-07-02 04:52:33.509 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.509 if eqi is None:
2025-07-02 04:52:33.509 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.509 atags = btags = ""
2025-07-02 04:52:33.509 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.509 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.509 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.509 if tag == 'replace':
2025-07-02 04:52:33.509 atags += '^' * la
2025-07-02 04:52:33.509 btags += '^' * lb
2025-07-02 04:52:33.509 elif tag == 'delete':
2025-07-02 04:52:33.510 atags += '-' * la
2025-07-02 04:52:33.510 elif tag == 'insert':
2025-07-02 04:52:33.510 btags += '+' * lb
2025-07-02 04:52:33.510 elif tag == 'equal':
2025-07-02 04:52:33.510 atags += ' ' * la
2025-07-02 04:52:33.510 btags += ' ' * lb
2025-07-02 04:52:33.510 else:
2025-07-02 04:52:33.510 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.510 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.510 else:
2025-07-02 04:52:33.510 # the synch pair is identical
2025-07-02 04:52:33.510 yield ' ' + aelt
2025-07-02 04:52:33.510
2025-07-02 04:52:33.510 # pump out diffs from after the synch point
2025-07-02 04:52:33.510 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.510
2025-07-02 04:52:33.510 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.510 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.510
2025-07-02 04:52:33.510 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.510 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.511 alo = 419, ahi = 1101
2025-07-02 04:52:33.511 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.511 blo = 419, bhi = 1101
2025-07-02 04:52:33.511
2025-07-02 04:52:33.511 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.511 g = []
2025-07-02 04:52:33.511 if alo < ahi:
2025-07-02 04:52:33.511 if blo < bhi:
2025-07-02 04:52:33.511 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.511 else:
2025-07-02 04:52:33.511 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.511 elif blo < bhi:
2025-07-02 04:52:33.511 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.511
2025-07-02 04:52:33.511 > yield from g
2025-07-02 04:52:33.511
2025-07-02 04:52:33.511 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.511 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.511
2025-07-02 04:52:33.511 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.511 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.511 alo = 419, ahi = 1101
2025-07-02 04:52:33.512 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.512 blo = 419, bhi = 1101
2025-07-02 04:52:33.512
2025-07-02 04:52:33.512 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.512 r"""
2025-07-02 04:52:33.512 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.512 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.512 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.512 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.512
2025-07-02 04:52:33.512 Example:
2025-07-02 04:52:33.512
2025-07-02 04:52:33.512 >>> d = Differ()
2025-07-02 04:52:33.512 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.512 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.512 >>> print(''.join(results), end="")
2025-07-02 04:52:33.512 - abcDefghiJkl
2025-07-02 04:52:33.512 + abcdefGhijkl
2025-07-02 04:52:33.512 """
2025-07-02 04:52:33.512
2025-07-02 04:52:33.513 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.513 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.513 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.513 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.513 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.513
2025-07-02 04:52:33.513 # search for the pair that matches best without being identical
2025-07-02 04:52:33.513 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.513 # on junk -- unless we have to)
2025-07-02 04:52:33.513 for j in range(blo, bhi):
2025-07-02 04:52:33.513 bj = b[j]
2025-07-02 04:52:33.513 cruncher.set_seq2(bj)
2025-07-02 04:52:33.513 for i in range(alo, ahi):
2025-07-02 04:52:33.513 ai = a[i]
2025-07-02 04:52:33.513 if ai == bj:
2025-07-02 04:52:33.513 if eqi is None:
2025-07-02 04:52:33.513 eqi, eqj = i, j
2025-07-02 04:52:33.513 continue
2025-07-02 04:52:33.513 cruncher.set_seq1(ai)
2025-07-02 04:52:33.514 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.514 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.514 # compares by a factor of 3.
2025-07-02 04:52:33.514 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.514 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.514 # of the computation is cached by cruncher
2025-07-02 04:52:33.514 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.514 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.514 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.514 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.514 if best_ratio < cutoff:
2025-07-02 04:52:33.514 # no non-identical "pretty close" pair
2025-07-02 04:52:33.514 if eqi is None:
2025-07-02 04:52:33.514 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.514 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.514 return
2025-07-02 04:52:33.514 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.514 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.514 else:
2025-07-02 04:52:33.514 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.515 eqi = None
2025-07-02 04:52:33.515
2025-07-02 04:52:33.515 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.515 # identical
2025-07-02 04:52:33.515
2025-07-02 04:52:33.515 # pump out diffs from before the synch point
2025-07-02 04:52:33.515 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.515
2025-07-02 04:52:33.515 # do intraline marking on the synch pair
2025-07-02 04:52:33.515 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.515 if eqi is None:
2025-07-02 04:52:33.515 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.515 atags = btags = ""
2025-07-02 04:52:33.515 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.515 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.515 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.515 if tag == 'replace':
2025-07-02 04:52:33.515 atags += '^' * la
2025-07-02 04:52:33.515 btags += '^' * lb
2025-07-02 04:52:33.515 elif tag == 'delete':
2025-07-02 04:52:33.515 atags += '-' * la
2025-07-02 04:52:33.515 elif tag == 'insert':
2025-07-02 04:52:33.516 btags += '+' * lb
2025-07-02 04:52:33.516 elif tag == 'equal':
2025-07-02 04:52:33.516 atags += ' ' * la
2025-07-02 04:52:33.516 btags += ' ' * lb
2025-07-02 04:52:33.516 else:
2025-07-02 04:52:33.516 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.516 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.516 else:
2025-07-02 04:52:33.516 # the synch pair is identical
2025-07-02 04:52:33.516 yield ' ' + aelt
2025-07-02 04:52:33.516
2025-07-02 04:52:33.516 # pump out diffs from after the synch point
2025-07-02 04:52:33.516 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.516
2025-07-02 04:52:33.516 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.516 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.516
2025-07-02 04:52:33.516 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.516 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.516 alo = 422, ahi = 1101
2025-07-02 04:52:33.517 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.517 blo = 422, bhi = 1101
2025-07-02 04:52:33.517
2025-07-02 04:52:33.517 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.517 g = []
2025-07-02 04:52:33.517 if alo < ahi:
2025-07-02 04:52:33.517 if blo < bhi:
2025-07-02 04:52:33.517 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.517 else:
2025-07-02 04:52:33.517 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.517 elif blo < bhi:
2025-07-02 04:52:33.517 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.517
2025-07-02 04:52:33.517 > yield from g
2025-07-02 04:52:33.517
2025-07-02 04:52:33.517 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.517 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.517
2025-07-02 04:52:33.517 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.517 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.517 alo = 422, ahi = 1101
2025-07-02 04:52:33.518 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.518 blo = 422, bhi = 1101
2025-07-02 04:52:33.518
2025-07-02 04:52:33.518 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.518 r"""
2025-07-02 04:52:33.518 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.518 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.518 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.518 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.518
2025-07-02 04:52:33.518 Example:
2025-07-02 04:52:33.518
2025-07-02 04:52:33.518 >>> d = Differ()
2025-07-02 04:52:33.518 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.518 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.518 >>> print(''.join(results), end="")
2025-07-02 04:52:33.518 - abcDefghiJkl
2025-07-02 04:52:33.518 + abcdefGhijkl
2025-07-02 04:52:33.518 """
2025-07-02 04:52:33.519
2025-07-02 04:52:33.519 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.519 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.519 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.519 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.519 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.519
2025-07-02 04:52:33.519 # search for the pair that matches best without being identical
2025-07-02 04:52:33.519 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.519 # on junk -- unless we have to)
2025-07-02 04:52:33.519 for j in range(blo, bhi):
2025-07-02 04:52:33.519 bj = b[j]
2025-07-02 04:52:33.519 cruncher.set_seq2(bj)
2025-07-02 04:52:33.519 for i in range(alo, ahi):
2025-07-02 04:52:33.519 ai = a[i]
2025-07-02 04:52:33.519 if ai == bj:
2025-07-02 04:52:33.519 if eqi is None:
2025-07-02 04:52:33.519 eqi, eqj = i, j
2025-07-02 04:52:33.519 continue
2025-07-02 04:52:33.519 cruncher.set_seq1(ai)
2025-07-02 04:52:33.519 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.519 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.520 # compares by a factor of 3.
2025-07-02 04:52:33.520 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.520 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.520 # of the computation is cached by cruncher
2025-07-02 04:52:33.520 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.520 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.520 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.520 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.520 if best_ratio < cutoff:
2025-07-02 04:52:33.520 # no non-identical "pretty close" pair
2025-07-02 04:52:33.520 if eqi is None:
2025-07-02 04:52:33.520 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.520 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.520 return
2025-07-02 04:52:33.520 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.520 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.520 else:
2025-07-02 04:52:33.520 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.520 eqi = None
2025-07-02 04:52:33.520
2025-07-02 04:52:33.520 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.521 # identical
2025-07-02 04:52:33.521
2025-07-02 04:52:33.521 # pump out diffs from before the synch point
2025-07-02 04:52:33.521 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.521
2025-07-02 04:52:33.521 # do intraline marking on the synch pair
2025-07-02 04:52:33.521 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.521 if eqi is None:
2025-07-02 04:52:33.521 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.521 atags = btags = ""
2025-07-02 04:52:33.521 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.521 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.521 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.521 if tag == 'replace':
2025-07-02 04:52:33.521 atags += '^' * la
2025-07-02 04:52:33.521 btags += '^' * lb
2025-07-02 04:52:33.521 elif tag == 'delete':
2025-07-02 04:52:33.521 atags += '-' * la
2025-07-02 04:52:33.521 elif tag == 'insert':
2025-07-02 04:52:33.521 btags += '+' * lb
2025-07-02 04:52:33.522 elif tag == 'equal':
2025-07-02 04:52:33.522 atags += ' ' * la
2025-07-02 04:52:33.522 btags += ' ' * lb
2025-07-02 04:52:33.522 else:
2025-07-02 04:52:33.522 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.522 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.522 else:
2025-07-02 04:52:33.522 # the synch pair is identical
2025-07-02 04:52:33.522 yield ' ' + aelt
2025-07-02 04:52:33.522
2025-07-02 04:52:33.522 # pump out diffs from after the synch point
2025-07-02 04:52:33.522 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.522
2025-07-02 04:52:33.522 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.522 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.522
2025-07-02 04:52:33.522 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.522 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.522 alo = 423, ahi = 1101
2025-07-02 04:52:33.523 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.523 blo = 423, bhi = 1101
2025-07-02 04:52:33.523
2025-07-02 04:52:33.523 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.523 g = []
2025-07-02 04:52:33.523 if alo < ahi:
2025-07-02 04:52:33.523 if blo < bhi:
2025-07-02 04:52:33.523 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.523 else:
2025-07-02 04:52:33.523 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.523 elif blo < bhi:
2025-07-02 04:52:33.523 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.523
2025-07-02 04:52:33.523 > yield from g
2025-07-02 04:52:33.523
2025-07-02 04:52:33.523 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.523 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.523
2025-07-02 04:52:33.523 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.523 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.524 alo = 423, ahi = 1101
2025-07-02 04:52:33.524 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.524 blo = 423, bhi = 1101
2025-07-02 04:52:33.524
2025-07-02 04:52:33.524 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.524 r"""
2025-07-02 04:52:33.524 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.524 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.524 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.524 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.524
2025-07-02 04:52:33.524 Example:
2025-07-02 04:52:33.524
2025-07-02 04:52:33.524 >>> d = Differ()
2025-07-02 04:52:33.524 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.524 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.524 >>> print(''.join(results), end="")
2025-07-02 04:52:33.524 - abcDefghiJkl
2025-07-02 04:52:33.524 + abcdefGhijkl
2025-07-02 04:52:33.525 """
2025-07-02 04:52:33.525
2025-07-02 04:52:33.525 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.525 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.525 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.525 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.525 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.525
2025-07-02 04:52:33.525 # search for the pair that matches best without being identical
2025-07-02 04:52:33.525 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.525 # on junk -- unless we have to)
2025-07-02 04:52:33.525 for j in range(blo, bhi):
2025-07-02 04:52:33.525 bj = b[j]
2025-07-02 04:52:33.525 cruncher.set_seq2(bj)
2025-07-02 04:52:33.525 for i in range(alo, ahi):
2025-07-02 04:52:33.525 ai = a[i]
2025-07-02 04:52:33.525 if ai == bj:
2025-07-02 04:52:33.525 if eqi is None:
2025-07-02 04:52:33.525 eqi, eqj = i, j
2025-07-02 04:52:33.525 continue
2025-07-02 04:52:33.525 cruncher.set_seq1(ai)
2025-07-02 04:52:33.525 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.526 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.526 # compares by a factor of 3.
2025-07-02 04:52:33.526 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.526 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.526 # of the computation is cached by cruncher
2025-07-02 04:52:33.526 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.526 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.526 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.526 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.526 if best_ratio < cutoff:
2025-07-02 04:52:33.526 # no non-identical "pretty close" pair
2025-07-02 04:52:33.526 if eqi is None:
2025-07-02 04:52:33.526 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.526 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.526 return
2025-07-02 04:52:33.526 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.526 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.526 else:
2025-07-02 04:52:33.526 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.526 eqi = None
2025-07-02 04:52:33.526
2025-07-02 04:52:33.527 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.527 # identical
2025-07-02 04:52:33.527
2025-07-02 04:52:33.527 # pump out diffs from before the synch point
2025-07-02 04:52:33.527 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.527
2025-07-02 04:52:33.527 # do intraline marking on the synch pair
2025-07-02 04:52:33.527 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.527 if eqi is None:
2025-07-02 04:52:33.527 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.527 atags = btags = ""
2025-07-02 04:52:33.527 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.527 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.527 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.527 if tag == 'replace':
2025-07-02 04:52:33.527 atags += '^' * la
2025-07-02 04:52:33.527 btags += '^' * lb
2025-07-02 04:52:33.527 elif tag == 'delete':
2025-07-02 04:52:33.527 atags += '-' * la
2025-07-02 04:52:33.527 elif tag == 'insert':
2025-07-02 04:52:33.527 btags += '+' * lb
2025-07-02 04:52:33.527 elif tag == 'equal':
2025-07-02 04:52:33.528 atags += ' ' * la
2025-07-02 04:52:33.528 btags += ' ' * lb
2025-07-02 04:52:33.528 else:
2025-07-02 04:52:33.528 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.528 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.528 else:
2025-07-02 04:52:33.528 # the synch pair is identical
2025-07-02 04:52:33.528 yield ' ' + aelt
2025-07-02 04:52:33.528
2025-07-02 04:52:33.528 # pump out diffs from after the synch point
2025-07-02 04:52:33.528 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.528
2025-07-02 04:52:33.528 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.528 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.528
2025-07-02 04:52:33.528 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.528 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.528 alo = 424, ahi = 1101
2025-07-02 04:52:33.528 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.528 blo = 424, bhi = 1101
2025-07-02 04:52:33.528
2025-07-02 04:52:33.529 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.529 g = []
2025-07-02 04:52:33.529 if alo < ahi:
2025-07-02 04:52:33.529 if blo < bhi:
2025-07-02 04:52:33.529 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.529 else:
2025-07-02 04:52:33.529 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.529 elif blo < bhi:
2025-07-02 04:52:33.529 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.529
2025-07-02 04:52:33.529 > yield from g
2025-07-02 04:52:33.529
2025-07-02 04:52:33.529 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.529 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.529
2025-07-02 04:52:33.529 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.529 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.529 alo = 424, ahi = 1101
2025-07-02 04:52:33.529 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.530 blo = 424, bhi = 1101
2025-07-02 04:52:33.530
2025-07-02 04:52:33.530 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.530 r"""
2025-07-02 04:52:33.530 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.530 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.530 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.530 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.530
2025-07-02 04:52:33.530 Example:
2025-07-02 04:52:33.530
2025-07-02 04:52:33.530 >>> d = Differ()
2025-07-02 04:52:33.530 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.530 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.530 >>> print(''.join(results), end="")
2025-07-02 04:52:33.530 - abcDefghiJkl
2025-07-02 04:52:33.530 + abcdefGhijkl
2025-07-02 04:52:33.530 """
2025-07-02 04:52:33.530
2025-07-02 04:52:33.531 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.531 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.531 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.531 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.531 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.531
2025-07-02 04:52:33.531 # search for the pair that matches best without being identical
2025-07-02 04:52:33.531 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.531 # on junk -- unless we have to)
2025-07-02 04:52:33.531 for j in range(blo, bhi):
2025-07-02 04:52:33.531 bj = b[j]
2025-07-02 04:52:33.531 cruncher.set_seq2(bj)
2025-07-02 04:52:33.531 for i in range(alo, ahi):
2025-07-02 04:52:33.531 ai = a[i]
2025-07-02 04:52:33.531 if ai == bj:
2025-07-02 04:52:33.531 if eqi is None:
2025-07-02 04:52:33.531 eqi, eqj = i, j
2025-07-02 04:52:33.531 continue
2025-07-02 04:52:33.531 cruncher.set_seq1(ai)
2025-07-02 04:52:33.531 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.532 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.532 # compares by a factor of 3.
2025-07-02 04:52:33.532 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.532 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.532 # of the computation is cached by cruncher
2025-07-02 04:52:33.532 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.532 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.532 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.532 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.532 if best_ratio < cutoff:
2025-07-02 04:52:33.532 # no non-identical "pretty close" pair
2025-07-02 04:52:33.532 if eqi is None:
2025-07-02 04:52:33.532 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.532 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.532 return
2025-07-02 04:52:33.532 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.532 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.532 else:
2025-07-02 04:52:33.532 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.532 eqi = None
2025-07-02 04:52:33.532
2025-07-02 04:52:33.532 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.533 # identical
2025-07-02 04:52:33.533
2025-07-02 04:52:33.533 # pump out diffs from before the synch point
2025-07-02 04:52:33.533 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.533
2025-07-02 04:52:33.533 # do intraline marking on the synch pair
2025-07-02 04:52:33.533 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.533 if eqi is None:
2025-07-02 04:52:33.533 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.533 atags = btags = ""
2025-07-02 04:52:33.533 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.533 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.533 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.533 if tag == 'replace':
2025-07-02 04:52:33.533 atags += '^' * la
2025-07-02 04:52:33.533 btags += '^' * lb
2025-07-02 04:52:33.533 elif tag == 'delete':
2025-07-02 04:52:33.533 atags += '-' * la
2025-07-02 04:52:33.533 elif tag == 'insert':
2025-07-02 04:52:33.533 btags += '+' * lb
2025-07-02 04:52:33.533 elif tag == 'equal':
2025-07-02 04:52:33.534 atags += ' ' * la
2025-07-02 04:52:33.534 btags += ' ' * lb
2025-07-02 04:52:33.534 else:
2025-07-02 04:52:33.534 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.534 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.534 else:
2025-07-02 04:52:33.534 # the synch pair is identical
2025-07-02 04:52:33.534 yield ' ' + aelt
2025-07-02 04:52:33.534
2025-07-02 04:52:33.534 # pump out diffs from after the synch point
2025-07-02 04:52:33.534 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.534
2025-07-02 04:52:33.534 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.534 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.534
2025-07-02 04:52:33.534 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.534 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.534 alo = 425, ahi = 1101
2025-07-02 04:52:33.534 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.534 blo = 425, bhi = 1101
2025-07-02 04:52:33.534
2025-07-02 04:52:33.534 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.535 g = []
2025-07-02 04:52:33.535 if alo < ahi:
2025-07-02 04:52:33.535 if blo < bhi:
2025-07-02 04:52:33.535 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.535 else:
2025-07-02 04:52:33.535 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.535 elif blo < bhi:
2025-07-02 04:52:33.535 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.535
2025-07-02 04:52:33.535 > yield from g
2025-07-02 04:52:33.535
2025-07-02 04:52:33.535 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.535 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.535
2025-07-02 04:52:33.535 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.535 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.535 alo = 425, ahi = 1101
2025-07-02 04:52:33.535 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.535 blo = 425, bhi = 1101
2025-07-02 04:52:33.535
2025-07-02 04:52:33.535 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.536 r"""
2025-07-02 04:52:33.536 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.536 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.536 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.536 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.536
2025-07-02 04:52:33.536 Example:
2025-07-02 04:52:33.536
2025-07-02 04:52:33.536 >>> d = Differ()
2025-07-02 04:52:33.536 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.536 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.536 >>> print(''.join(results), end="")
2025-07-02 04:52:33.536 - abcDefghiJkl
2025-07-02 04:52:33.536 + abcdefGhijkl
2025-07-02 04:52:33.536 """
2025-07-02 04:52:33.536
2025-07-02 04:52:33.536 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.536 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.536 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.537 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.537 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.537
2025-07-02 04:52:33.537 # search for the pair that matches best without being identical
2025-07-02 04:52:33.537 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.537 # on junk -- unless we have to)
2025-07-02 04:52:33.537 for j in range(blo, bhi):
2025-07-02 04:52:33.537 bj = b[j]
2025-07-02 04:52:33.537 cruncher.set_seq2(bj)
2025-07-02 04:52:33.537 for i in range(alo, ahi):
2025-07-02 04:52:33.537 ai = a[i]
2025-07-02 04:52:33.537 if ai == bj:
2025-07-02 04:52:33.537 if eqi is None:
2025-07-02 04:52:33.537 eqi, eqj = i, j
2025-07-02 04:52:33.537 continue
2025-07-02 04:52:33.537 cruncher.set_seq1(ai)
2025-07-02 04:52:33.537 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.537 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.537 # compares by a factor of 3.
2025-07-02 04:52:33.537 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.537 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.538 # of the computation is cached by cruncher
2025-07-02 04:52:33.538 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.538 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.538 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.538 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.538 if best_ratio < cutoff:
2025-07-02 04:52:33.538 # no non-identical "pretty close" pair
2025-07-02 04:52:33.538 if eqi is None:
2025-07-02 04:52:33.538 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.538 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.538 return
2025-07-02 04:52:33.538 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.538 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.538 else:
2025-07-02 04:52:33.538 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.538 eqi = None
2025-07-02 04:52:33.538
2025-07-02 04:52:33.538 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.538 # identical
2025-07-02 04:52:33.538
2025-07-02 04:52:33.539 # pump out diffs from before the synch point
2025-07-02 04:52:33.539 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.539
2025-07-02 04:52:33.539 # do intraline marking on the synch pair
2025-07-02 04:52:33.539 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.539 if eqi is None:
2025-07-02 04:52:33.539 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.539 atags = btags = ""
2025-07-02 04:52:33.539 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.539 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.539 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.539 if tag == 'replace':
2025-07-02 04:52:33.539 atags += '^' * la
2025-07-02 04:52:33.539 btags += '^' * lb
2025-07-02 04:52:33.539 elif tag == 'delete':
2025-07-02 04:52:33.539 atags += '-' * la
2025-07-02 04:52:33.539 elif tag == 'insert':
2025-07-02 04:52:33.539 btags += '+' * lb
2025-07-02 04:52:33.539 elif tag == 'equal':
2025-07-02 04:52:33.539 atags += ' ' * la
2025-07-02 04:52:33.539 btags += ' ' * lb
2025-07-02 04:52:33.540 else:
2025-07-02 04:52:33.540 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.540 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.540 else:
2025-07-02 04:52:33.540 # the synch pair is identical
2025-07-02 04:52:33.540 yield ' ' + aelt
2025-07-02 04:52:33.540
2025-07-02 04:52:33.540 # pump out diffs from after the synch point
2025-07-02 04:52:33.540 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.540
2025-07-02 04:52:33.540 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.540 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.540
2025-07-02 04:52:33.540 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.540 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.540 alo = 426, ahi = 1101
2025-07-02 04:52:33.540 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.540 blo = 426, bhi = 1101
2025-07-02 04:52:33.540
2025-07-02 04:52:33.540 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.540 g = []
2025-07-02 04:52:33.541 if alo < ahi:
2025-07-02 04:52:33.541 if blo < bhi:
2025-07-02 04:52:33.541 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.541 else:
2025-07-02 04:52:33.541 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.541 elif blo < bhi:
2025-07-02 04:52:33.541 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.541
2025-07-02 04:52:33.541 > yield from g
2025-07-02 04:52:33.541
2025-07-02 04:52:33.541 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.541 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.541
2025-07-02 04:52:33.541 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.541 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.541 alo = 426, ahi = 1101
2025-07-02 04:52:33.541 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.541 blo = 426, bhi = 1101
2025-07-02 04:52:33.541
2025-07-02 04:52:33.541 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.541 r"""
2025-07-02 04:52:33.541 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.542 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.542 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.542 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.542
2025-07-02 04:52:33.542 Example:
2025-07-02 04:52:33.542
2025-07-02 04:52:33.542 >>> d = Differ()
2025-07-02 04:52:33.542 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.542 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.542 >>> print(''.join(results), end="")
2025-07-02 04:52:33.542 - abcDefghiJkl
2025-07-02 04:52:33.542 + abcdefGhijkl
2025-07-02 04:52:33.542 """
2025-07-02 04:52:33.542
2025-07-02 04:52:33.542 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.542 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.542 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.542 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.542 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.543
2025-07-02 04:52:33.543 # search for the pair that matches best without being identical
2025-07-02 04:52:33.543 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.543 # on junk -- unless we have to)
2025-07-02 04:52:33.543 for j in range(blo, bhi):
2025-07-02 04:52:33.543 bj = b[j]
2025-07-02 04:52:33.543 cruncher.set_seq2(bj)
2025-07-02 04:52:33.543 for i in range(alo, ahi):
2025-07-02 04:52:33.543 ai = a[i]
2025-07-02 04:52:33.543 if ai == bj:
2025-07-02 04:52:33.543 if eqi is None:
2025-07-02 04:52:33.543 eqi, eqj = i, j
2025-07-02 04:52:33.543 continue
2025-07-02 04:52:33.543 cruncher.set_seq1(ai)
2025-07-02 04:52:33.543 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.543 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.543 # compares by a factor of 3.
2025-07-02 04:52:33.543 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.543 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.543 # of the computation is cached by cruncher
2025-07-02 04:52:33.544 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.544 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.544 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.544 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.544 if best_ratio < cutoff:
2025-07-02 04:52:33.544 # no non-identical "pretty close" pair
2025-07-02 04:52:33.544 if eqi is None:
2025-07-02 04:52:33.544 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.544 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.544 return
2025-07-02 04:52:33.544 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.544 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.544 else:
2025-07-02 04:52:33.544 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.544 eqi = None
2025-07-02 04:52:33.544
2025-07-02 04:52:33.544 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.544 # identical
2025-07-02 04:52:33.544
2025-07-02 04:52:33.544 # pump out diffs from before the synch point
2025-07-02 04:52:33.544 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.545
2025-07-02 04:52:33.545 # do intraline marking on the synch pair
2025-07-02 04:52:33.545 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.545 if eqi is None:
2025-07-02 04:52:33.545 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.545 atags = btags = ""
2025-07-02 04:52:33.545 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.545 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.545 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.545 if tag == 'replace':
2025-07-02 04:52:33.545 atags += '^' * la
2025-07-02 04:52:33.545 btags += '^' * lb
2025-07-02 04:52:33.545 elif tag == 'delete':
2025-07-02 04:52:33.545 atags += '-' * la
2025-07-02 04:52:33.545 elif tag == 'insert':
2025-07-02 04:52:33.545 btags += '+' * lb
2025-07-02 04:52:33.545 elif tag == 'equal':
2025-07-02 04:52:33.545 atags += ' ' * la
2025-07-02 04:52:33.545 btags += ' ' * lb
2025-07-02 04:52:33.545 else:
2025-07-02 04:52:33.545 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.545 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.546 else:
2025-07-02 04:52:33.546 # the synch pair is identical
2025-07-02 04:52:33.546 yield ' ' + aelt
2025-07-02 04:52:33.546
2025-07-02 04:52:33.546 # pump out diffs from after the synch point
2025-07-02 04:52:33.546 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.546
2025-07-02 04:52:33.546 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.546 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.546
2025-07-02 04:52:33.546 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.546 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.546 alo = 427, ahi = 1101
2025-07-02 04:52:33.546 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.546 blo = 427, bhi = 1101
2025-07-02 04:52:33.546
2025-07-02 04:52:33.546 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.546 g = []
2025-07-02 04:52:33.546 if alo < ahi:
2025-07-02 04:52:33.546 if blo < bhi:
2025-07-02 04:52:33.547 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.547 else:
2025-07-02 04:52:33.547 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.547 elif blo < bhi:
2025-07-02 04:52:33.547 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.547
2025-07-02 04:52:33.547 > yield from g
2025-07-02 04:52:33.547
2025-07-02 04:52:33.547 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.547 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.547
2025-07-02 04:52:33.547 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.547 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.547 alo = 427, ahi = 1101
2025-07-02 04:52:33.547 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.547 blo = 427, bhi = 1101
2025-07-02 04:52:33.547
2025-07-02 04:52:33.547 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.547 r"""
2025-07-02 04:52:33.547 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.548 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.548 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.548 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.548
2025-07-02 04:52:33.548 Example:
2025-07-02 04:52:33.548
2025-07-02 04:52:33.548 >>> d = Differ()
2025-07-02 04:52:33.548 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.548 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.548 >>> print(''.join(results), end="")
2025-07-02 04:52:33.548 - abcDefghiJkl
2025-07-02 04:52:33.548 + abcdefGhijkl
2025-07-02 04:52:33.548 """
2025-07-02 04:52:33.548
2025-07-02 04:52:33.548 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.548 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.548 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.548 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.548 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.549
2025-07-02 04:52:33.549 # search for the pair that matches best without being identical
2025-07-02 04:52:33.549 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.549 # on junk -- unless we have to)
2025-07-02 04:52:33.549 for j in range(blo, bhi):
2025-07-02 04:52:33.549 bj = b[j]
2025-07-02 04:52:33.549 cruncher.set_seq2(bj)
2025-07-02 04:52:33.549 for i in range(alo, ahi):
2025-07-02 04:52:33.549 ai = a[i]
2025-07-02 04:52:33.549 if ai == bj:
2025-07-02 04:52:33.549 if eqi is None:
2025-07-02 04:52:33.549 eqi, eqj = i, j
2025-07-02 04:52:33.549 continue
2025-07-02 04:52:33.549 cruncher.set_seq1(ai)
2025-07-02 04:52:33.549 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.549 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.549 # compares by a factor of 3.
2025-07-02 04:52:33.549 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.549 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.549 # of the computation is cached by cruncher
2025-07-02 04:52:33.549 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.549 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.550 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.550 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.550 if best_ratio < cutoff:
2025-07-02 04:52:33.550 # no non-identical "pretty close" pair
2025-07-02 04:52:33.550 if eqi is None:
2025-07-02 04:52:33.550 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.550 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.550 return
2025-07-02 04:52:33.550 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.550 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.550 else:
2025-07-02 04:52:33.550 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.550 eqi = None
2025-07-02 04:52:33.550
2025-07-02 04:52:33.550 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.550 # identical
2025-07-02 04:52:33.550
2025-07-02 04:52:33.550 # pump out diffs from before the synch point
2025-07-02 04:52:33.550 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.550
2025-07-02 04:52:33.550 # do intraline marking on the synch pair
2025-07-02 04:52:33.551 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.551 if eqi is None:
2025-07-02 04:52:33.551 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.551 atags = btags = ""
2025-07-02 04:52:33.551 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.551 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.551 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.551 if tag == 'replace':
2025-07-02 04:52:33.551 atags += '^' * la
2025-07-02 04:52:33.551 btags += '^' * lb
2025-07-02 04:52:33.551 elif tag == 'delete':
2025-07-02 04:52:33.551 atags += '-' * la
2025-07-02 04:52:33.551 elif tag == 'insert':
2025-07-02 04:52:33.551 btags += '+' * lb
2025-07-02 04:52:33.551 elif tag == 'equal':
2025-07-02 04:52:33.551 atags += ' ' * la
2025-07-02 04:52:33.551 btags += ' ' * lb
2025-07-02 04:52:33.551 else:
2025-07-02 04:52:33.551 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.551 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.551 else:
2025-07-02 04:52:33.551 # the synch pair is identical
2025-07-02 04:52:33.552 yield ' ' + aelt
2025-07-02 04:52:33.552
2025-07-02 04:52:33.552 # pump out diffs from after the synch point
2025-07-02 04:52:33.552 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.552
2025-07-02 04:52:33.552 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.552 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.552
2025-07-02 04:52:33.552 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.552 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.552 alo = 428, ahi = 1101
2025-07-02 04:52:33.552 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.552 blo = 428, bhi = 1101
2025-07-02 04:52:33.552
2025-07-02 04:52:33.552 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.552 g = []
2025-07-02 04:52:33.552 if alo < ahi:
2025-07-02 04:52:33.552 if blo < bhi:
2025-07-02 04:52:33.552 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.552 else:
2025-07-02 04:52:33.552 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.553 elif blo < bhi:
2025-07-02 04:52:33.553 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.553
2025-07-02 04:52:33.553 > yield from g
2025-07-02 04:52:33.553
2025-07-02 04:52:33.553 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.553 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.553
2025-07-02 04:52:33.553 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.553 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.553 alo = 428, ahi = 1101
2025-07-02 04:52:33.553 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.553 blo = 428, bhi = 1101
2025-07-02 04:52:33.553
2025-07-02 04:52:33.553 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.553 r"""
2025-07-02 04:52:33.553 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.553 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.553 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.553 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.553
2025-07-02 04:52:33.554 Example:
2025-07-02 04:52:33.554
2025-07-02 04:52:33.554 >>> d = Differ()
2025-07-02 04:52:33.554 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.554 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.554 >>> print(''.join(results), end="")
2025-07-02 04:52:33.554 - abcDefghiJkl
2025-07-02 04:52:33.554 + abcdefGhijkl
2025-07-02 04:52:33.554 """
2025-07-02 04:52:33.554
2025-07-02 04:52:33.554 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.554 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.554 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.554 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.554 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.554
2025-07-02 04:52:33.554 # search for the pair that matches best without being identical
2025-07-02 04:52:33.554 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.555 # on junk -- unless we have to)
2025-07-02 04:52:33.555 for j in range(blo, bhi):
2025-07-02 04:52:33.555 bj = b[j]
2025-07-02 04:52:33.555 cruncher.set_seq2(bj)
2025-07-02 04:52:33.555 for i in range(alo, ahi):
2025-07-02 04:52:33.555 ai = a[i]
2025-07-02 04:52:33.555 if ai == bj:
2025-07-02 04:52:33.555 if eqi is None:
2025-07-02 04:52:33.555 eqi, eqj = i, j
2025-07-02 04:52:33.555 continue
2025-07-02 04:52:33.555 cruncher.set_seq1(ai)
2025-07-02 04:52:33.555 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.555 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.555 # compares by a factor of 3.
2025-07-02 04:52:33.555 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.555 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.555 # of the computation is cached by cruncher
2025-07-02 04:52:33.555 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.555 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.555 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.556 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.556 if best_ratio < cutoff:
2025-07-02 04:52:33.556 # no non-identical "pretty close" pair
2025-07-02 04:52:33.556 if eqi is None:
2025-07-02 04:52:33.556 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.556 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.556 return
2025-07-02 04:52:33.556 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.556 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.556 else:
2025-07-02 04:52:33.556 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.556 eqi = None
2025-07-02 04:52:33.556
2025-07-02 04:52:33.556 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.556 # identical
2025-07-02 04:52:33.556
2025-07-02 04:52:33.556 # pump out diffs from before the synch point
2025-07-02 04:52:33.556 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.556
2025-07-02 04:52:33.556 # do intraline marking on the synch pair
2025-07-02 04:52:33.556 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.556 if eqi is None:
2025-07-02 04:52:33.557 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.557 atags = btags = ""
2025-07-02 04:52:33.557 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.557 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.557 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.557 if tag == 'replace':
2025-07-02 04:52:33.557 atags += '^' * la
2025-07-02 04:52:33.557 btags += '^' * lb
2025-07-02 04:52:33.557 elif tag == 'delete':
2025-07-02 04:52:33.557 atags += '-' * la
2025-07-02 04:52:33.557 elif tag == 'insert':
2025-07-02 04:52:33.557 btags += '+' * lb
2025-07-02 04:52:33.557 elif tag == 'equal':
2025-07-02 04:52:33.557 atags += ' ' * la
2025-07-02 04:52:33.557 btags += ' ' * lb
2025-07-02 04:52:33.557 else:
2025-07-02 04:52:33.557 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.557 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.557 else:
2025-07-02 04:52:33.557 # the synch pair is identical
2025-07-02 04:52:33.557 yield ' ' + aelt
2025-07-02 04:52:33.558
2025-07-02 04:52:33.558 # pump out diffs from after the synch point
2025-07-02 04:52:33.558 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.558
2025-07-02 04:52:33.558 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.558 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.558
2025-07-02 04:52:33.558 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.558 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.558 alo = 429, ahi = 1101
2025-07-02 04:52:33.558 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.558 blo = 429, bhi = 1101
2025-07-02 04:52:33.558
2025-07-02 04:52:33.558 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.558 g = []
2025-07-02 04:52:33.558 if alo < ahi:
2025-07-02 04:52:33.558 if blo < bhi:
2025-07-02 04:52:33.558 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.558 else:
2025-07-02 04:52:33.558 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.558 elif blo < bhi:
2025-07-02 04:52:33.558 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.559
2025-07-02 04:52:33.559 > yield from g
2025-07-02 04:52:33.559
2025-07-02 04:52:33.559 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.559 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.559
2025-07-02 04:52:33.559 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.559 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.559 alo = 429, ahi = 1101
2025-07-02 04:52:33.559 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.559 blo = 429, bhi = 1101
2025-07-02 04:52:33.559
2025-07-02 04:52:33.559 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.559 r"""
2025-07-02 04:52:33.559 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.559 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.559 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.559 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.559
2025-07-02 04:52:33.559 Example:
2025-07-02 04:52:33.560
2025-07-02 04:52:33.560 >>> d = Differ()
2025-07-02 04:52:33.560 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.560 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.560 >>> print(''.join(results), end="")
2025-07-02 04:52:33.560 - abcDefghiJkl
2025-07-02 04:52:33.560 + abcdefGhijkl
2025-07-02 04:52:33.560 """
2025-07-02 04:52:33.560
2025-07-02 04:52:33.560 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.560 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.560 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.560 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.560 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.560
2025-07-02 04:52:33.560 # search for the pair that matches best without being identical
2025-07-02 04:52:33.560 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.560 # on junk -- unless we have to)
2025-07-02 04:52:33.560 for j in range(blo, bhi):
2025-07-02 04:52:33.560 bj = b[j]
2025-07-02 04:52:33.561 cruncher.set_seq2(bj)
2025-07-02 04:52:33.561 for i in range(alo, ahi):
2025-07-02 04:52:33.561 ai = a[i]
2025-07-02 04:52:33.561 if ai == bj:
2025-07-02 04:52:33.561 if eqi is None:
2025-07-02 04:52:33.561 eqi, eqj = i, j
2025-07-02 04:52:33.561 continue
2025-07-02 04:52:33.561 cruncher.set_seq1(ai)
2025-07-02 04:52:33.561 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.561 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.561 # compares by a factor of 3.
2025-07-02 04:52:33.561 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.561 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.561 # of the computation is cached by cruncher
2025-07-02 04:52:33.561 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.561 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.561 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.561 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.561 if best_ratio < cutoff:
2025-07-02 04:52:33.561 # no non-identical "pretty close" pair
2025-07-02 04:52:33.561 if eqi is None:
2025-07-02 04:52:33.562 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.562 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.562 return
2025-07-02 04:52:33.562 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.562 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.562 else:
2025-07-02 04:52:33.562 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.562 eqi = None
2025-07-02 04:52:33.562
2025-07-02 04:52:33.562 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.562 # identical
2025-07-02 04:52:33.562
2025-07-02 04:52:33.562 # pump out diffs from before the synch point
2025-07-02 04:52:33.562 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.562
2025-07-02 04:52:33.562 # do intraline marking on the synch pair
2025-07-02 04:52:33.562 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.562 if eqi is None:
2025-07-02 04:52:33.562 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.562 atags = btags = ""
2025-07-02 04:52:33.563 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.563 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.563 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.563 if tag == 'replace':
2025-07-02 04:52:33.563 atags += '^' * la
2025-07-02 04:52:33.563 btags += '^' * lb
2025-07-02 04:52:33.563 elif tag == 'delete':
2025-07-02 04:52:33.563 atags += '-' * la
2025-07-02 04:52:33.563 elif tag == 'insert':
2025-07-02 04:52:33.563 btags += '+' * lb
2025-07-02 04:52:33.563 elif tag == 'equal':
2025-07-02 04:52:33.563 atags += ' ' * la
2025-07-02 04:52:33.563 btags += ' ' * lb
2025-07-02 04:52:33.563 else:
2025-07-02 04:52:33.563 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.563 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.563 else:
2025-07-02 04:52:33.563 # the synch pair is identical
2025-07-02 04:52:33.563 yield ' ' + aelt
2025-07-02 04:52:33.563
2025-07-02 04:52:33.563 # pump out diffs from after the synch point
2025-07-02 04:52:33.564 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.564
2025-07-02 04:52:33.564 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.564 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.564
2025-07-02 04:52:33.564 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.564 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.564 alo = 430, ahi = 1101
2025-07-02 04:52:33.564 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.564 blo = 430, bhi = 1101
2025-07-02 04:52:33.564
2025-07-02 04:52:33.564 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.564 g = []
2025-07-02 04:52:33.564 if alo < ahi:
2025-07-02 04:52:33.564 if blo < bhi:
2025-07-02 04:52:33.564 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.564 else:
2025-07-02 04:52:33.564 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.564 elif blo < bhi:
2025-07-02 04:52:33.564 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.565
2025-07-02 04:52:33.565 > yield from g
2025-07-02 04:52:33.565
2025-07-02 04:52:33.565 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.565 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.565
2025-07-02 04:52:33.565 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.565 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.565 alo = 430, ahi = 1101
2025-07-02 04:52:33.565 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.565 blo = 430, bhi = 1101
2025-07-02 04:52:33.565
2025-07-02 04:52:33.565 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.565 r"""
2025-07-02 04:52:33.565 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.565 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.565 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.565 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.565
2025-07-02 04:52:33.565 Example:
2025-07-02 04:52:33.565
2025-07-02 04:52:33.566 >>> d = Differ()
2025-07-02 04:52:33.566 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.566 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.566 >>> print(''.join(results), end="")
2025-07-02 04:52:33.566 - abcDefghiJkl
2025-07-02 04:52:33.566 + abcdefGhijkl
2025-07-02 04:52:33.566 """
2025-07-02 04:52:33.566
2025-07-02 04:52:33.566 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.566 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.566 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.566 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.566 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.566
2025-07-02 04:52:33.566 # search for the pair that matches best without being identical
2025-07-02 04:52:33.566 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.566 # on junk -- unless we have to)
2025-07-02 04:52:33.566 for j in range(blo, bhi):
2025-07-02 04:52:33.566 bj = b[j]
2025-07-02 04:52:33.567 cruncher.set_seq2(bj)
2025-07-02 04:52:33.567 for i in range(alo, ahi):
2025-07-02 04:52:33.567 ai = a[i]
2025-07-02 04:52:33.567 if ai == bj:
2025-07-02 04:52:33.567 if eqi is None:
2025-07-02 04:52:33.567 eqi, eqj = i, j
2025-07-02 04:52:33.567 continue
2025-07-02 04:52:33.567 cruncher.set_seq1(ai)
2025-07-02 04:52:33.567 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.567 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.567 # compares by a factor of 3.
2025-07-02 04:52:33.567 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.567 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.567 # of the computation is cached by cruncher
2025-07-02 04:52:33.567 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.567 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.567 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.567 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.567 if best_ratio < cutoff:
2025-07-02 04:52:33.567 # no non-identical "pretty close" pair
2025-07-02 04:52:33.567 if eqi is None:
2025-07-02 04:52:33.567 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.568 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.568 return
2025-07-02 04:52:33.568 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.568 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.568 else:
2025-07-02 04:52:33.568 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.568 eqi = None
2025-07-02 04:52:33.568
2025-07-02 04:52:33.568 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.568 # identical
2025-07-02 04:52:33.568
2025-07-02 04:52:33.568 # pump out diffs from before the synch point
2025-07-02 04:52:33.568 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.568
2025-07-02 04:52:33.568 # do intraline marking on the synch pair
2025-07-02 04:52:33.568 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.568 if eqi is None:
2025-07-02 04:52:33.568 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.568 atags = btags = ""
2025-07-02 04:52:33.568 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.569 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.569 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.569 if tag == 'replace':
2025-07-02 04:52:33.569 atags += '^' * la
2025-07-02 04:52:33.569 btags += '^' * lb
2025-07-02 04:52:33.569 elif tag == 'delete':
2025-07-02 04:52:33.569 atags += '-' * la
2025-07-02 04:52:33.569 elif tag == 'insert':
2025-07-02 04:52:33.569 btags += '+' * lb
2025-07-02 04:52:33.569 elif tag == 'equal':
2025-07-02 04:52:33.569 atags += ' ' * la
2025-07-02 04:52:33.569 btags += ' ' * lb
2025-07-02 04:52:33.569 else:
2025-07-02 04:52:33.569 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.569 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.569 else:
2025-07-02 04:52:33.569 # the synch pair is identical
2025-07-02 04:52:33.569 yield ' ' + aelt
2025-07-02 04:52:33.569
2025-07-02 04:52:33.569 # pump out diffs from after the synch point
2025-07-02 04:52:33.569 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.570
2025-07-02 04:52:33.570 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.570 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.570
2025-07-02 04:52:33.570 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.570 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.570 alo = 431, ahi = 1101
2025-07-02 04:52:33.570 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.570 blo = 431, bhi = 1101
2025-07-02 04:52:33.570
2025-07-02 04:52:33.570 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.570 g = []
2025-07-02 04:52:33.570 if alo < ahi:
2025-07-02 04:52:33.570 if blo < bhi:
2025-07-02 04:52:33.570 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.570 else:
2025-07-02 04:52:33.570 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.570 elif blo < bhi:
2025-07-02 04:52:33.570 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.571
2025-07-02 04:52:33.571 > yield from g
2025-07-02 04:52:33.571
2025-07-02 04:52:33.571 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.571 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.571
2025-07-02 04:52:33.571 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.571 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.571 alo = 431, ahi = 1101
2025-07-02 04:52:33.571 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.571 blo = 431, bhi = 1101
2025-07-02 04:52:33.571
2025-07-02 04:52:33.571 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.571 r"""
2025-07-02 04:52:33.571 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.571 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.571 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.571 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.571
2025-07-02 04:52:33.571 Example:
2025-07-02 04:52:33.571
2025-07-02 04:52:33.572 >>> d = Differ()
2025-07-02 04:52:33.572 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.572 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.572 >>> print(''.join(results), end="")
2025-07-02 04:52:33.572 - abcDefghiJkl
2025-07-02 04:52:33.572 + abcdefGhijkl
2025-07-02 04:52:33.572 """
2025-07-02 04:52:33.572
2025-07-02 04:52:33.572 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.572 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.572 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.572 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.572 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.572
2025-07-02 04:52:33.572 # search for the pair that matches best without being identical
2025-07-02 04:52:33.572 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.572 # on junk -- unless we have to)
2025-07-02 04:52:33.572 for j in range(blo, bhi):
2025-07-02 04:52:33.573 bj = b[j]
2025-07-02 04:52:33.573 cruncher.set_seq2(bj)
2025-07-02 04:52:33.573 for i in range(alo, ahi):
2025-07-02 04:52:33.573 ai = a[i]
2025-07-02 04:52:33.573 if ai == bj:
2025-07-02 04:52:33.573 if eqi is None:
2025-07-02 04:52:33.573 eqi, eqj = i, j
2025-07-02 04:52:33.573 continue
2025-07-02 04:52:33.573 cruncher.set_seq1(ai)
2025-07-02 04:52:33.573 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.573 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.573 # compares by a factor of 3.
2025-07-02 04:52:33.573 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.573 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.573 # of the computation is cached by cruncher
2025-07-02 04:52:33.573 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.573 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.573 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.573 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.573 if best_ratio < cutoff:
2025-07-02 04:52:33.573 # no non-identical "pretty close" pair
2025-07-02 04:52:33.573 if eqi is None:
2025-07-02 04:52:33.574 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.574 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.574 return
2025-07-02 04:52:33.574 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.574 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.574 else:
2025-07-02 04:52:33.574 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.574 eqi = None
2025-07-02 04:52:33.574
2025-07-02 04:52:33.574 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.574 # identical
2025-07-02 04:52:33.574
2025-07-02 04:52:33.574 # pump out diffs from before the synch point
2025-07-02 04:52:33.574 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.574
2025-07-02 04:52:33.574 # do intraline marking on the synch pair
2025-07-02 04:52:33.574 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.574 if eqi is None:
2025-07-02 04:52:33.574 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.574 atags = btags = ""
2025-07-02 04:52:33.574 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.575 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.575 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.575 if tag == 'replace':
2025-07-02 04:52:33.575 atags += '^' * la
2025-07-02 04:52:33.575 btags += '^' * lb
2025-07-02 04:52:33.575 elif tag == 'delete':
2025-07-02 04:52:33.575 atags += '-' * la
2025-07-02 04:52:33.575 elif tag == 'insert':
2025-07-02 04:52:33.575 btags += '+' * lb
2025-07-02 04:52:33.575 elif tag == 'equal':
2025-07-02 04:52:33.575 atags += ' ' * la
2025-07-02 04:52:33.575 btags += ' ' * lb
2025-07-02 04:52:33.575 else:
2025-07-02 04:52:33.575 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.575 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.575 else:
2025-07-02 04:52:33.575 # the synch pair is identical
2025-07-02 04:52:33.575 yield ' ' + aelt
2025-07-02 04:52:33.575
2025-07-02 04:52:33.575 # pump out diffs from after the synch point
2025-07-02 04:52:33.575 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.575
2025-07-02 04:52:33.576 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.576 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.576
2025-07-02 04:52:33.576 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.576 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.576 alo = 432, ahi = 1101
2025-07-02 04:52:33.576 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.576 blo = 432, bhi = 1101
2025-07-02 04:52:33.576
2025-07-02 04:52:33.576 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.576 g = []
2025-07-02 04:52:33.576 if alo < ahi:
2025-07-02 04:52:33.576 if blo < bhi:
2025-07-02 04:52:33.576 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.576 else:
2025-07-02 04:52:33.576 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.576 elif blo < bhi:
2025-07-02 04:52:33.576 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.576
2025-07-02 04:52:33.576 > yield from g
2025-07-02 04:52:33.576
2025-07-02 04:52:33.577 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.577 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.577
2025-07-02 04:52:33.577 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.577 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.577 alo = 432, ahi = 1101
2025-07-02 04:52:33.577 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.577 blo = 432, bhi = 1101
2025-07-02 04:52:33.577
2025-07-02 04:52:33.577 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.577 r"""
2025-07-02 04:52:33.577 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.577 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.577 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.577 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.577
2025-07-02 04:52:33.577 Example:
2025-07-02 04:52:33.577
2025-07-02 04:52:33.577 >>> d = Differ()
2025-07-02 04:52:33.577 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.577 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.578 >>> print(''.join(results), end="")
2025-07-02 04:52:33.578 - abcDefghiJkl
2025-07-02 04:52:33.578 + abcdefGhijkl
2025-07-02 04:52:33.578 """
2025-07-02 04:52:33.578
2025-07-02 04:52:33.578 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.578 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.578 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.578 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.578 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.578
2025-07-02 04:52:33.578 # search for the pair that matches best without being identical
2025-07-02 04:52:33.578 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.578 # on junk -- unless we have to)
2025-07-02 04:52:33.578 for j in range(blo, bhi):
2025-07-02 04:52:33.578 bj = b[j]
2025-07-02 04:52:33.578 cruncher.set_seq2(bj)
2025-07-02 04:52:33.578 for i in range(alo, ahi):
2025-07-02 04:52:33.578 ai = a[i]
2025-07-02 04:52:33.579 if ai == bj:
2025-07-02 04:52:33.579 if eqi is None:
2025-07-02 04:52:33.579 eqi, eqj = i, j
2025-07-02 04:52:33.579 continue
2025-07-02 04:52:33.579 cruncher.set_seq1(ai)
2025-07-02 04:52:33.579 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.579 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.579 # compares by a factor of 3.
2025-07-02 04:52:33.579 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.579 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.579 # of the computation is cached by cruncher
2025-07-02 04:52:33.579 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.579 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.579 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.579 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.579 if best_ratio < cutoff:
2025-07-02 04:52:33.579 # no non-identical "pretty close" pair
2025-07-02 04:52:33.579 if eqi is None:
2025-07-02 04:52:33.579 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.579 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.580 return
2025-07-02 04:52:33.580 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.580 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.580 else:
2025-07-02 04:52:33.580 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.580 eqi = None
2025-07-02 04:52:33.580
2025-07-02 04:52:33.580 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.580 # identical
2025-07-02 04:52:33.580
2025-07-02 04:52:33.580 # pump out diffs from before the synch point
2025-07-02 04:52:33.580 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.580
2025-07-02 04:52:33.580 # do intraline marking on the synch pair
2025-07-02 04:52:33.580 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.580 if eqi is None:
2025-07-02 04:52:33.580 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.580 atags = btags = ""
2025-07-02 04:52:33.580 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.580 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.580 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.581 if tag == 'replace':
2025-07-02 04:52:33.581 atags += '^' * la
2025-07-02 04:52:33.581 btags += '^' * lb
2025-07-02 04:52:33.581 elif tag == 'delete':
2025-07-02 04:52:33.581 atags += '-' * la
2025-07-02 04:52:33.581 elif tag == 'insert':
2025-07-02 04:52:33.581 btags += '+' * lb
2025-07-02 04:52:33.581 elif tag == 'equal':
2025-07-02 04:52:33.581 atags += ' ' * la
2025-07-02 04:52:33.581 btags += ' ' * lb
2025-07-02 04:52:33.581 else:
2025-07-02 04:52:33.581 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.581 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.581 else:
2025-07-02 04:52:33.581 # the synch pair is identical
2025-07-02 04:52:33.581 yield ' ' + aelt
2025-07-02 04:52:33.581
2025-07-02 04:52:33.581 # pump out diffs from after the synch point
2025-07-02 04:52:33.581 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.581
2025-07-02 04:52:33.581 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.581 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.582
2025-07-02 04:52:33.582 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.582 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.582 alo = 433, ahi = 1101
2025-07-02 04:52:33.582 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.582 blo = 433, bhi = 1101
2025-07-02 04:52:33.582
2025-07-02 04:52:33.582 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.582 g = []
2025-07-02 04:52:33.582 if alo < ahi:
2025-07-02 04:52:33.582 if blo < bhi:
2025-07-02 04:52:33.582 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.582 else:
2025-07-02 04:52:33.582 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.582 elif blo < bhi:
2025-07-02 04:52:33.582 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.582
2025-07-02 04:52:33.582 > yield from g
2025-07-02 04:52:33.582
2025-07-02 04:52:33.582 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.582 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.583
2025-07-02 04:52:33.583 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.583 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.583 alo = 433, ahi = 1101
2025-07-02 04:52:33.583 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.583 blo = 433, bhi = 1101
2025-07-02 04:52:33.583
2025-07-02 04:52:33.583 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.583 r"""
2025-07-02 04:52:33.583 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.583 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.583 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.583 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.583
2025-07-02 04:52:33.583 Example:
2025-07-02 04:52:33.583
2025-07-02 04:52:33.583 >>> d = Differ()
2025-07-02 04:52:33.583 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.583 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.583 >>> print(''.join(results), end="")
2025-07-02 04:52:33.583 - abcDefghiJkl
2025-07-02 04:52:33.584 + abcdefGhijkl
2025-07-02 04:52:33.584 """
2025-07-02 04:52:33.584
2025-07-02 04:52:33.584 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.584 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.584 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.584 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.584 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.584
2025-07-02 04:52:33.584 # search for the pair that matches best without being identical
2025-07-02 04:52:33.584 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.584 # on junk -- unless we have to)
2025-07-02 04:52:33.584 for j in range(blo, bhi):
2025-07-02 04:52:33.584 bj = b[j]
2025-07-02 04:52:33.584 cruncher.set_seq2(bj)
2025-07-02 04:52:33.584 for i in range(alo, ahi):
2025-07-02 04:52:33.584 ai = a[i]
2025-07-02 04:52:33.584 if ai == bj:
2025-07-02 04:52:33.584 if eqi is None:
2025-07-02 04:52:33.585 eqi, eqj = i, j
2025-07-02 04:52:33.585 continue
2025-07-02 04:52:33.585 cruncher.set_seq1(ai)
2025-07-02 04:52:33.585 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.585 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.585 # compares by a factor of 3.
2025-07-02 04:52:33.585 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.585 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.585 # of the computation is cached by cruncher
2025-07-02 04:52:33.585 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.585 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.585 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.585 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.585 if best_ratio < cutoff:
2025-07-02 04:52:33.585 # no non-identical "pretty close" pair
2025-07-02 04:52:33.585 if eqi is None:
2025-07-02 04:52:33.585 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.585 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.585 return
2025-07-02 04:52:33.585 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.585 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.585 else:
2025-07-02 04:52:33.586 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.586 eqi = None
2025-07-02 04:52:33.586
2025-07-02 04:52:33.586 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.586 # identical
2025-07-02 04:52:33.586
2025-07-02 04:52:33.586 # pump out diffs from before the synch point
2025-07-02 04:52:33.586 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.586
2025-07-02 04:52:33.586 # do intraline marking on the synch pair
2025-07-02 04:52:33.586 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.586 if eqi is None:
2025-07-02 04:52:33.586 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.586 atags = btags = ""
2025-07-02 04:52:33.586 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.586 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.586 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.586 if tag == 'replace':
2025-07-02 04:52:33.587 atags += '^' * la
2025-07-02 04:52:33.587 btags += '^' * lb
2025-07-02 04:52:33.587 elif tag == 'delete':
2025-07-02 04:52:33.587 atags += '-' * la
2025-07-02 04:52:33.587 elif tag == 'insert':
2025-07-02 04:52:33.587 btags += '+' * lb
2025-07-02 04:52:33.587 elif tag == 'equal':
2025-07-02 04:52:33.587 atags += ' ' * la
2025-07-02 04:52:33.587 btags += ' ' * lb
2025-07-02 04:52:33.587 else:
2025-07-02 04:52:33.587 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.587 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.587 else:
2025-07-02 04:52:33.587 # the synch pair is identical
2025-07-02 04:52:33.587 yield ' ' + aelt
2025-07-02 04:52:33.587
2025-07-02 04:52:33.587 # pump out diffs from after the synch point
2025-07-02 04:52:33.587 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.587
2025-07-02 04:52:33.587 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.588 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.588
2025-07-02 04:52:33.588 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.588 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.588 alo = 434, ahi = 1101
2025-07-02 04:52:33.588 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.588 blo = 434, bhi = 1101
2025-07-02 04:52:33.588
2025-07-02 04:52:33.588 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.588 g = []
2025-07-02 04:52:33.588 if alo < ahi:
2025-07-02 04:52:33.588 if blo < bhi:
2025-07-02 04:52:33.588 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.588 else:
2025-07-02 04:52:33.588 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.588 elif blo < bhi:
2025-07-02 04:52:33.588 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.588
2025-07-02 04:52:33.588 > yield from g
2025-07-02 04:52:33.588
2025-07-02 04:52:33.589 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.589 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.589
2025-07-02 04:52:33.589 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.589 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.589 alo = 434, ahi = 1101
2025-07-02 04:52:33.589 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.589 blo = 434, bhi = 1101
2025-07-02 04:52:33.589
2025-07-02 04:52:33.589 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.589 r"""
2025-07-02 04:52:33.589 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.589 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.589 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.589 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.589
2025-07-02 04:52:33.589 Example:
2025-07-02 04:52:33.589
2025-07-02 04:52:33.589 >>> d = Differ()
2025-07-02 04:52:33.589 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.590 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.590 >>> print(''.join(results), end="")
2025-07-02 04:52:33.590 - abcDefghiJkl
2025-07-02 04:52:33.590 + abcdefGhijkl
2025-07-02 04:52:33.590 """
2025-07-02 04:52:33.590
2025-07-02 04:52:33.590 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.590 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.590 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.590 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.590 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.590
2025-07-02 04:52:33.590 # search for the pair that matches best without being identical
2025-07-02 04:52:33.590 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.590 # on junk -- unless we have to)
2025-07-02 04:52:33.590 for j in range(blo, bhi):
2025-07-02 04:52:33.590 bj = b[j]
2025-07-02 04:52:33.590 cruncher.set_seq2(bj)
2025-07-02 04:52:33.590 for i in range(alo, ahi):
2025-07-02 04:52:33.591 ai = a[i]
2025-07-02 04:52:33.591 if ai == bj:
2025-07-02 04:52:33.591 if eqi is None:
2025-07-02 04:52:33.591 eqi, eqj = i, j
2025-07-02 04:52:33.591 continue
2025-07-02 04:52:33.591 cruncher.set_seq1(ai)
2025-07-02 04:52:33.591 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.591 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.591 # compares by a factor of 3.
2025-07-02 04:52:33.591 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.591 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.591 # of the computation is cached by cruncher
2025-07-02 04:52:33.591 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.591 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.591 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.591 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.591 if best_ratio < cutoff:
2025-07-02 04:52:33.591 # no non-identical "pretty close" pair
2025-07-02 04:52:33.591 if eqi is None:
2025-07-02 04:52:33.591 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.591 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.592 return
2025-07-02 04:52:33.592 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.592 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.592 else:
2025-07-02 04:52:33.592 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.592 eqi = None
2025-07-02 04:52:33.592
2025-07-02 04:52:33.592 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.592 # identical
2025-07-02 04:52:33.592
2025-07-02 04:52:33.592 # pump out diffs from before the synch point
2025-07-02 04:52:33.592 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.592
2025-07-02 04:52:33.592 # do intraline marking on the synch pair
2025-07-02 04:52:33.592 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.592 if eqi is None:
2025-07-02 04:52:33.592 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.592 atags = btags = ""
2025-07-02 04:52:33.592 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.592 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.592 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.593 if tag == 'replace':
2025-07-02 04:52:33.593 atags += '^' * la
2025-07-02 04:52:33.593 btags += '^' * lb
2025-07-02 04:52:33.593 elif tag == 'delete':
2025-07-02 04:52:33.593 atags += '-' * la
2025-07-02 04:52:33.593 elif tag == 'insert':
2025-07-02 04:52:33.593 btags += '+' * lb
2025-07-02 04:52:33.593 elif tag == 'equal':
2025-07-02 04:52:33.593 atags += ' ' * la
2025-07-02 04:52:33.593 btags += ' ' * lb
2025-07-02 04:52:33.593 else:
2025-07-02 04:52:33.593 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.593 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.593 else:
2025-07-02 04:52:33.593 # the synch pair is identical
2025-07-02 04:52:33.593 yield ' ' + aelt
2025-07-02 04:52:33.593
2025-07-02 04:52:33.593 # pump out diffs from after the synch point
2025-07-02 04:52:33.593 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.593
2025-07-02 04:52:33.594 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.594 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.594
2025-07-02 04:52:33.594 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.594 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.594 alo = 435, ahi = 1101
2025-07-02 04:52:33.594 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.594 blo = 435, bhi = 1101
2025-07-02 04:52:33.594
2025-07-02 04:52:33.594 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.594 g = []
2025-07-02 04:52:33.594 if alo < ahi:
2025-07-02 04:52:33.594 if blo < bhi:
2025-07-02 04:52:33.594 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.594 else:
2025-07-02 04:52:33.594 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.594 elif blo < bhi:
2025-07-02 04:52:33.594 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.594
2025-07-02 04:52:33.594 > yield from g
2025-07-02 04:52:33.594
2025-07-02 04:52:33.595 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.595 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.595
2025-07-02 04:52:33.595 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.595 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.595 alo = 435, ahi = 1101
2025-07-02 04:52:33.595 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.595 blo = 435, bhi = 1101
2025-07-02 04:52:33.595
2025-07-02 04:52:33.595 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.595 r"""
2025-07-02 04:52:33.595 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.595 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.595 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.595 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.595
2025-07-02 04:52:33.595 Example:
2025-07-02 04:52:33.595
2025-07-02 04:52:33.595 >>> d = Differ()
2025-07-02 04:52:33.596 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.596 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.596 >>> print(''.join(results), end="")
2025-07-02 04:52:33.596 - abcDefghiJkl
2025-07-02 04:52:33.596 + abcdefGhijkl
2025-07-02 04:52:33.596 """
2025-07-02 04:52:33.596
2025-07-02 04:52:33.596 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.596 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.596 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.596 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.596 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.596
2025-07-02 04:52:33.596 # search for the pair that matches best without being identical
2025-07-02 04:52:33.596 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.596 # on junk -- unless we have to)
2025-07-02 04:52:33.596 for j in range(blo, bhi):
2025-07-02 04:52:33.596 bj = b[j]
2025-07-02 04:52:33.597 cruncher.set_seq2(bj)
2025-07-02 04:52:33.597 for i in range(alo, ahi):
2025-07-02 04:52:33.597 ai = a[i]
2025-07-02 04:52:33.597 if ai == bj:
2025-07-02 04:52:33.597 if eqi is None:
2025-07-02 04:52:33.597 eqi, eqj = i, j
2025-07-02 04:52:33.597 continue
2025-07-02 04:52:33.597 cruncher.set_seq1(ai)
2025-07-02 04:52:33.597 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.597 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.597 # compares by a factor of 3.
2025-07-02 04:52:33.597 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.597 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.597 # of the computation is cached by cruncher
2025-07-02 04:52:33.597 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.597 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.597 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.597 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.597 if best_ratio < cutoff:
2025-07-02 04:52:33.598 # no non-identical "pretty close" pair
2025-07-02 04:52:33.598 if eqi is None:
2025-07-02 04:52:33.598 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.598 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.598 return
2025-07-02 04:52:33.598 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.598 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.598 else:
2025-07-02 04:52:33.598 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.598 eqi = None
2025-07-02 04:52:33.598
2025-07-02 04:52:33.598 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.598 # identical
2025-07-02 04:52:33.598
2025-07-02 04:52:33.598 # pump out diffs from before the synch point
2025-07-02 04:52:33.598 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.598
2025-07-02 04:52:33.598 # do intraline marking on the synch pair
2025-07-02 04:52:33.598 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.598 if eqi is None:
2025-07-02 04:52:33.598 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.599 atags = btags = ""
2025-07-02 04:52:33.599 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.599 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.599 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.599 if tag == 'replace':
2025-07-02 04:52:33.599 atags += '^' * la
2025-07-02 04:52:33.599 btags += '^' * lb
2025-07-02 04:52:33.599 elif tag == 'delete':
2025-07-02 04:52:33.599 atags += '-' * la
2025-07-02 04:52:33.599 elif tag == 'insert':
2025-07-02 04:52:33.599 btags += '+' * lb
2025-07-02 04:52:33.599 elif tag == 'equal':
2025-07-02 04:52:33.599 atags += ' ' * la
2025-07-02 04:52:33.599 btags += ' ' * lb
2025-07-02 04:52:33.599 else:
2025-07-02 04:52:33.599 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.599 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.599 else:
2025-07-02 04:52:33.599 # the synch pair is identical
2025-07-02 04:52:33.599 yield ' ' + aelt
2025-07-02 04:52:33.599
2025-07-02 04:52:33.600 # pump out diffs from after the synch point
2025-07-02 04:52:33.600 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.600
2025-07-02 04:52:33.600 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.600 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.600
2025-07-02 04:52:33.600 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.600 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.600 alo = 436, ahi = 1101
2025-07-02 04:52:33.600 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.600 blo = 436, bhi = 1101
2025-07-02 04:52:33.600
2025-07-02 04:52:33.600 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.600 g = []
2025-07-02 04:52:33.600 if alo < ahi:
2025-07-02 04:52:33.600 if blo < bhi:
2025-07-02 04:52:33.600 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.600 else:
2025-07-02 04:52:33.600 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.600 elif blo < bhi:
2025-07-02 04:52:33.600 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.601
2025-07-02 04:52:33.601 > yield from g
2025-07-02 04:52:33.601
2025-07-02 04:52:33.601 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.601 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.601
2025-07-02 04:52:33.601 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.601 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.601 alo = 436, ahi = 1101
2025-07-02 04:52:33.601 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.601 blo = 436, bhi = 1101
2025-07-02 04:52:33.601
2025-07-02 04:52:33.601 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.601 r"""
2025-07-02 04:52:33.601 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.601 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.601 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.601 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.601
2025-07-02 04:52:33.601 Example:
2025-07-02 04:52:33.601
2025-07-02 04:52:33.602 >>> d = Differ()
2025-07-02 04:52:33.602 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.602 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.602 >>> print(''.join(results), end="")
2025-07-02 04:52:33.602 - abcDefghiJkl
2025-07-02 04:52:33.602 + abcdefGhijkl
2025-07-02 04:52:33.602 """
2025-07-02 04:52:33.602
2025-07-02 04:52:33.602 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.602 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.602 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.602 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.602 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.602
2025-07-02 04:52:33.602 # search for the pair that matches best without being identical
2025-07-02 04:52:33.602 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.602 # on junk -- unless we have to)
2025-07-02 04:52:33.602 for j in range(blo, bhi):
2025-07-02 04:52:33.603 bj = b[j]
2025-07-02 04:52:33.603 cruncher.set_seq2(bj)
2025-07-02 04:52:33.603 for i in range(alo, ahi):
2025-07-02 04:52:33.603 ai = a[i]
2025-07-02 04:52:33.603 if ai == bj:
2025-07-02 04:52:33.603 if eqi is None:
2025-07-02 04:52:33.603 eqi, eqj = i, j
2025-07-02 04:52:33.603 continue
2025-07-02 04:52:33.603 cruncher.set_seq1(ai)
2025-07-02 04:52:33.603 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.603 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.603 # compares by a factor of 3.
2025-07-02 04:52:33.603 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.603 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.603 # of the computation is cached by cruncher
2025-07-02 04:52:33.603 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.603 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.603 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.603 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.603 if best_ratio < cutoff:
2025-07-02 04:52:33.603 # no non-identical "pretty close" pair
2025-07-02 04:52:33.604 if eqi is None:
2025-07-02 04:52:33.604 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.604 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.604 return
2025-07-02 04:52:33.604 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.604 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.604 else:
2025-07-02 04:52:33.604 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.604 eqi = None
2025-07-02 04:52:33.604
2025-07-02 04:52:33.604 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.604 # identical
2025-07-02 04:52:33.604
2025-07-02 04:52:33.604 # pump out diffs from before the synch point
2025-07-02 04:52:33.604 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.604
2025-07-02 04:52:33.604 # do intraline marking on the synch pair
2025-07-02 04:52:33.604 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.605 if eqi is None:
2025-07-02 04:52:33.605 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.605 atags = btags = ""
2025-07-02 04:52:33.605 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.605 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.605 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.605 if tag == 'replace':
2025-07-02 04:52:33.605 atags += '^' * la
2025-07-02 04:52:33.605 btags += '^' * lb
2025-07-02 04:52:33.605 elif tag == 'delete':
2025-07-02 04:52:33.605 atags += '-' * la
2025-07-02 04:52:33.605 elif tag == 'insert':
2025-07-02 04:52:33.605 btags += '+' * lb
2025-07-02 04:52:33.605 elif tag == 'equal':
2025-07-02 04:52:33.605 atags += ' ' * la
2025-07-02 04:52:33.605 btags += ' ' * lb
2025-07-02 04:52:33.605 else:
2025-07-02 04:52:33.605 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.605 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.605 else:
2025-07-02 04:52:33.606 # the synch pair is identical
2025-07-02 04:52:33.606 yield ' ' + aelt
2025-07-02 04:52:33.606
2025-07-02 04:52:33.606 # pump out diffs from after the synch point
2025-07-02 04:52:33.606 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.606
2025-07-02 04:52:33.606 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.606 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.606
2025-07-02 04:52:33.606 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.606 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.606 alo = 437, ahi = 1101
2025-07-02 04:52:33.606 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.606 blo = 437, bhi = 1101
2025-07-02 04:52:33.606
2025-07-02 04:52:33.606 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.606 g = []
2025-07-02 04:52:33.606 if alo < ahi:
2025-07-02 04:52:33.606 if blo < bhi:
2025-07-02 04:52:33.606 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.606 else:
2025-07-02 04:52:33.607 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.607 elif blo < bhi:
2025-07-02 04:52:33.607 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.607
2025-07-02 04:52:33.607 > yield from g
2025-07-02 04:52:33.607
2025-07-02 04:52:33.607 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.607 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.607
2025-07-02 04:52:33.607 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.607 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.607 alo = 437, ahi = 1101
2025-07-02 04:52:33.607 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.607 blo = 437, bhi = 1101
2025-07-02 04:52:33.607
2025-07-02 04:52:33.607 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.607 r"""
2025-07-02 04:52:33.607 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.607 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.607 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.607 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.608
2025-07-02 04:52:33.608 Example:
2025-07-02 04:52:33.608
2025-07-02 04:52:33.608 >>> d = Differ()
2025-07-02 04:52:33.608 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.608 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.608 >>> print(''.join(results), end="")
2025-07-02 04:52:33.608 - abcDefghiJkl
2025-07-02 04:52:33.608 + abcdefGhijkl
2025-07-02 04:52:33.608 """
2025-07-02 04:52:33.608
2025-07-02 04:52:33.608 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.608 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.608 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.608 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.608 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.608
2025-07-02 04:52:33.608 # search for the pair that matches best without being identical
2025-07-02 04:52:33.608 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.609 # on junk -- unless we have to)
2025-07-02 04:52:33.609 for j in range(blo, bhi):
2025-07-02 04:52:33.609 bj = b[j]
2025-07-02 04:52:33.609 cruncher.set_seq2(bj)
2025-07-02 04:52:33.609 for i in range(alo, ahi):
2025-07-02 04:52:33.609 ai = a[i]
2025-07-02 04:52:33.609 if ai == bj:
2025-07-02 04:52:33.609 if eqi is None:
2025-07-02 04:52:33.609 eqi, eqj = i, j
2025-07-02 04:52:33.609 continue
2025-07-02 04:52:33.609 cruncher.set_seq1(ai)
2025-07-02 04:52:33.609 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.609 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.609 # compares by a factor of 3.
2025-07-02 04:52:33.609 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.609 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.609 # of the computation is cached by cruncher
2025-07-02 04:52:33.609 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.609 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.609 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.609 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.609 if best_ratio < cutoff:
2025-07-02 04:52:33.610 # no non-identical "pretty close" pair
2025-07-02 04:52:33.610 if eqi is None:
2025-07-02 04:52:33.610 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.610 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.610 return
2025-07-02 04:52:33.610 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.610 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.610 else:
2025-07-02 04:52:33.610 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.610 eqi = None
2025-07-02 04:52:33.610
2025-07-02 04:52:33.610 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.610 # identical
2025-07-02 04:52:33.610
2025-07-02 04:52:33.610 # pump out diffs from before the synch point
2025-07-02 04:52:33.610 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.610
2025-07-02 04:52:33.610 # do intraline marking on the synch pair
2025-07-02 04:52:33.610 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.610 if eqi is None:
2025-07-02 04:52:33.610 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.611 atags = btags = ""
2025-07-02 04:52:33.611 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.611 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.611 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.611 if tag == 'replace':
2025-07-02 04:52:33.611 atags += '^' * la
2025-07-02 04:52:33.611 btags += '^' * lb
2025-07-02 04:52:33.611 elif tag == 'delete':
2025-07-02 04:52:33.611 atags += '-' * la
2025-07-02 04:52:33.611 elif tag == 'insert':
2025-07-02 04:52:33.611 btags += '+' * lb
2025-07-02 04:52:33.611 elif tag == 'equal':
2025-07-02 04:52:33.611 atags += ' ' * la
2025-07-02 04:52:33.611 btags += ' ' * lb
2025-07-02 04:52:33.611 else:
2025-07-02 04:52:33.611 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.611 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.611 else:
2025-07-02 04:52:33.612 # the synch pair is identical
2025-07-02 04:52:33.612 yield ' ' + aelt
2025-07-02 04:52:33.612
2025-07-02 04:52:33.612 # pump out diffs from after the synch point
2025-07-02 04:52:33.612 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.612
2025-07-02 04:52:33.612 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.612 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.612
2025-07-02 04:52:33.612 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.612 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.612 alo = 438, ahi = 1101
2025-07-02 04:52:33.612 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.612 blo = 438, bhi = 1101
2025-07-02 04:52:33.612
2025-07-02 04:52:33.612 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.612 g = []
2025-07-02 04:52:33.612 if alo < ahi:
2025-07-02 04:52:33.612 if blo < bhi:
2025-07-02 04:52:33.613 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.613 else:
2025-07-02 04:52:33.613 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.613 elif blo < bhi:
2025-07-02 04:52:33.613 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.613
2025-07-02 04:52:33.613 > yield from g
2025-07-02 04:52:33.613
2025-07-02 04:52:33.613 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.613 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.613
2025-07-02 04:52:33.613 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.613 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.613 alo = 438, ahi = 1101
2025-07-02 04:52:33.613 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.613 blo = 438, bhi = 1101
2025-07-02 04:52:33.613
2025-07-02 04:52:33.613 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.613 r"""
2025-07-02 04:52:33.613 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.614 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.614 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.614 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.614
2025-07-02 04:52:33.614 Example:
2025-07-02 04:52:33.614
2025-07-02 04:52:33.614 >>> d = Differ()
2025-07-02 04:52:33.614 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.614 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.614 >>> print(''.join(results), end="")
2025-07-02 04:52:33.614 - abcDefghiJkl
2025-07-02 04:52:33.614 + abcdefGhijkl
2025-07-02 04:52:33.614 """
2025-07-02 04:52:33.614
2025-07-02 04:52:33.614 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.614 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.614 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.614 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.615 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.615
2025-07-02 04:52:33.615 # search for the pair that matches best without being identical
2025-07-02 04:52:33.615 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.615 # on junk -- unless we have to)
2025-07-02 04:52:33.615 for j in range(blo, bhi):
2025-07-02 04:52:33.615 bj = b[j]
2025-07-02 04:52:33.615 cruncher.set_seq2(bj)
2025-07-02 04:52:33.615 for i in range(alo, ahi):
2025-07-02 04:52:33.615 ai = a[i]
2025-07-02 04:52:33.615 if ai == bj:
2025-07-02 04:52:33.615 if eqi is None:
2025-07-02 04:52:33.615 eqi, eqj = i, j
2025-07-02 04:52:33.615 continue
2025-07-02 04:52:33.615 cruncher.set_seq1(ai)
2025-07-02 04:52:33.615 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.615 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.615 # compares by a factor of 3.
2025-07-02 04:52:33.615 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.615 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.615 # of the computation is cached by cruncher
2025-07-02 04:52:33.615 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.616 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.616 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.616 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.616 if best_ratio < cutoff:
2025-07-02 04:52:33.616 # no non-identical "pretty close" pair
2025-07-02 04:52:33.616 if eqi is None:
2025-07-02 04:52:33.616 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.616 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.616 return
2025-07-02 04:52:33.616 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.616 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.616 else:
2025-07-02 04:52:33.616 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.616 eqi = None
2025-07-02 04:52:33.616
2025-07-02 04:52:33.616 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.616 # identical
2025-07-02 04:52:33.616
2025-07-02 04:52:33.616 # pump out diffs from before the synch point
2025-07-02 04:52:33.616 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.616
2025-07-02 04:52:33.617 # do intraline marking on the synch pair
2025-07-02 04:52:33.617 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.617 if eqi is None:
2025-07-02 04:52:33.617 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.617 atags = btags = ""
2025-07-02 04:52:33.617 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.617 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.617 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.617 if tag == 'replace':
2025-07-02 04:52:33.617 atags += '^' * la
2025-07-02 04:52:33.617 btags += '^' * lb
2025-07-02 04:52:33.617 elif tag == 'delete':
2025-07-02 04:52:33.617 atags += '-' * la
2025-07-02 04:52:33.617 elif tag == 'insert':
2025-07-02 04:52:33.617 btags += '+' * lb
2025-07-02 04:52:33.617 elif tag == 'equal':
2025-07-02 04:52:33.617 atags += ' ' * la
2025-07-02 04:52:33.617 btags += ' ' * lb
2025-07-02 04:52:33.617 else:
2025-07-02 04:52:33.617 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.617 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.617 else:
2025-07-02 04:52:33.618 # the synch pair is identical
2025-07-02 04:52:33.618 yield ' ' + aelt
2025-07-02 04:52:33.618
2025-07-02 04:52:33.618 # pump out diffs from after the synch point
2025-07-02 04:52:33.618 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.618
2025-07-02 04:52:33.618 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.618 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.618
2025-07-02 04:52:33.618 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.618 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.618 alo = 439, ahi = 1101
2025-07-02 04:52:33.618 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.618 blo = 439, bhi = 1101
2025-07-02 04:52:33.618
2025-07-02 04:52:33.618 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.618 g = []
2025-07-02 04:52:33.618 if alo < ahi:
2025-07-02 04:52:33.619 if blo < bhi:
2025-07-02 04:52:33.619 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.619 else:
2025-07-02 04:52:33.619 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.619 elif blo < bhi:
2025-07-02 04:52:33.619 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.619
2025-07-02 04:52:33.619 > yield from g
2025-07-02 04:52:33.619
2025-07-02 04:52:33.619 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.619 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.619
2025-07-02 04:52:33.619 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.619 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.619 alo = 439, ahi = 1101
2025-07-02 04:52:33.619 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.619 blo = 439, bhi = 1101
2025-07-02 04:52:33.619
2025-07-02 04:52:33.619 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.619 r"""
2025-07-02 04:52:33.619 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.620 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.620 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.620 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.620
2025-07-02 04:52:33.620 Example:
2025-07-02 04:52:33.620
2025-07-02 04:52:33.620 >>> d = Differ()
2025-07-02 04:52:33.620 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.620 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.620 >>> print(''.join(results), end="")
2025-07-02 04:52:33.620 - abcDefghiJkl
2025-07-02 04:52:33.620 + abcdefGhijkl
2025-07-02 04:52:33.620 """
2025-07-02 04:52:33.620
2025-07-02 04:52:33.620 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.620 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.620 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.620 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.620 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.621
2025-07-02 04:52:33.621 # search for the pair that matches best without being identical
2025-07-02 04:52:33.621 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.621 # on junk -- unless we have to)
2025-07-02 04:52:33.621 for j in range(blo, bhi):
2025-07-02 04:52:33.621 bj = b[j]
2025-07-02 04:52:33.621 cruncher.set_seq2(bj)
2025-07-02 04:52:33.621 for i in range(alo, ahi):
2025-07-02 04:52:33.621 ai = a[i]
2025-07-02 04:52:33.621 if ai == bj:
2025-07-02 04:52:33.621 if eqi is None:
2025-07-02 04:52:33.621 eqi, eqj = i, j
2025-07-02 04:52:33.621 continue
2025-07-02 04:52:33.621 cruncher.set_seq1(ai)
2025-07-02 04:52:33.621 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.621 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.621 # compares by a factor of 3.
2025-07-02 04:52:33.621 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.621 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.621 # of the computation is cached by cruncher
2025-07-02 04:52:33.622 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.622 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.622 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.622 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.622 if best_ratio < cutoff:
2025-07-02 04:52:33.622 # no non-identical "pretty close" pair
2025-07-02 04:52:33.622 if eqi is None:
2025-07-02 04:52:33.622 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.622 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.622 return
2025-07-02 04:52:33.622 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.622 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.622 else:
2025-07-02 04:52:33.622 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.622 eqi = None
2025-07-02 04:52:33.622
2025-07-02 04:52:33.622 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.622 # identical
2025-07-02 04:52:33.622
2025-07-02 04:52:33.622 # pump out diffs from before the synch point
2025-07-02 04:52:33.622 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.623
2025-07-02 04:52:33.623 # do intraline marking on the synch pair
2025-07-02 04:52:33.623 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.623 if eqi is None:
2025-07-02 04:52:33.623 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.623 atags = btags = ""
2025-07-02 04:52:33.623 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.623 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.623 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.623 if tag == 'replace':
2025-07-02 04:52:33.623 atags += '^' * la
2025-07-02 04:52:33.623 btags += '^' * lb
2025-07-02 04:52:33.623 elif tag == 'delete':
2025-07-02 04:52:33.623 atags += '-' * la
2025-07-02 04:52:33.623 elif tag == 'insert':
2025-07-02 04:52:33.623 btags += '+' * lb
2025-07-02 04:52:33.623 elif tag == 'equal':
2025-07-02 04:52:33.623 atags += ' ' * la
2025-07-02 04:52:33.623 btags += ' ' * lb
2025-07-02 04:52:33.623 else:
2025-07-02 04:52:33.623 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.624 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.624 else:
2025-07-02 04:52:33.624 # the synch pair is identical
2025-07-02 04:52:33.624 yield ' ' + aelt
2025-07-02 04:52:33.624
2025-07-02 04:52:33.624 # pump out diffs from after the synch point
2025-07-02 04:52:33.624 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.624
2025-07-02 04:52:33.624 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.624 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.624
2025-07-02 04:52:33.624 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.624 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.624 alo = 440, ahi = 1101
2025-07-02 04:52:33.624 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.624 blo = 440, bhi = 1101
2025-07-02 04:52:33.624
2025-07-02 04:52:33.624 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.624 g = []
2025-07-02 04:52:33.624 if alo < ahi:
2025-07-02 04:52:33.624 if blo < bhi:
2025-07-02 04:52:33.624 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.625 else:
2025-07-02 04:52:33.625 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.625 elif blo < bhi:
2025-07-02 04:52:33.625 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.625
2025-07-02 04:52:33.625 > yield from g
2025-07-02 04:52:33.625
2025-07-02 04:52:33.625 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.625 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.625
2025-07-02 04:52:33.625 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.625 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.625 alo = 440, ahi = 1101
2025-07-02 04:52:33.625 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.625 blo = 440, bhi = 1101
2025-07-02 04:52:33.625
2025-07-02 04:52:33.625 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.625 r"""
2025-07-02 04:52:33.625 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.625 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.625 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.626 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.626
2025-07-02 04:52:33.626 Example:
2025-07-02 04:52:33.626
2025-07-02 04:52:33.626 >>> d = Differ()
2025-07-02 04:52:33.626 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.626 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.626 >>> print(''.join(results), end="")
2025-07-02 04:52:33.626 - abcDefghiJkl
2025-07-02 04:52:33.626 + abcdefGhijkl
2025-07-02 04:52:33.626 """
2025-07-02 04:52:33.626
2025-07-02 04:52:33.626 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.626 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.626 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.626 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.626 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.626
2025-07-02 04:52:33.626 # search for the pair that matches best without being identical
2025-07-02 04:52:33.627 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.627 # on junk -- unless we have to)
2025-07-02 04:52:33.627 for j in range(blo, bhi):
2025-07-02 04:52:33.627 bj = b[j]
2025-07-02 04:52:33.627 cruncher.set_seq2(bj)
2025-07-02 04:52:33.627 for i in range(alo, ahi):
2025-07-02 04:52:33.627 ai = a[i]
2025-07-02 04:52:33.627 if ai == bj:
2025-07-02 04:52:33.627 if eqi is None:
2025-07-02 04:52:33.627 eqi, eqj = i, j
2025-07-02 04:52:33.627 continue
2025-07-02 04:52:33.627 cruncher.set_seq1(ai)
2025-07-02 04:52:33.627 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.627 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.627 # compares by a factor of 3.
2025-07-02 04:52:33.627 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.627 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.627 # of the computation is cached by cruncher
2025-07-02 04:52:33.627 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.627 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.627 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.627 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.628 if best_ratio < cutoff:
2025-07-02 04:52:33.628 # no non-identical "pretty close" pair
2025-07-02 04:52:33.628 if eqi is None:
2025-07-02 04:52:33.628 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.628 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.628 return
2025-07-02 04:52:33.628 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.628 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.628 else:
2025-07-02 04:52:33.628 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.628 eqi = None
2025-07-02 04:52:33.628
2025-07-02 04:52:33.628 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.628 # identical
2025-07-02 04:52:33.628
2025-07-02 04:52:33.628 # pump out diffs from before the synch point
2025-07-02 04:52:33.628 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.628
2025-07-02 04:52:33.628 # do intraline marking on the synch pair
2025-07-02 04:52:33.628 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.628 if eqi is None:
2025-07-02 04:52:33.629 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.629 atags = btags = ""
2025-07-02 04:52:33.629 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.629 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.629 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.629 if tag == 'replace':
2025-07-02 04:52:33.629 atags += '^' * la
2025-07-02 04:52:33.629 btags += '^' * lb
2025-07-02 04:52:33.629 elif tag == 'delete':
2025-07-02 04:52:33.629 atags += '-' * la
2025-07-02 04:52:33.629 elif tag == 'insert':
2025-07-02 04:52:33.629 btags += '+' * lb
2025-07-02 04:52:33.629 elif tag == 'equal':
2025-07-02 04:52:33.629 atags += ' ' * la
2025-07-02 04:52:33.629 btags += ' ' * lb
2025-07-02 04:52:33.629 else:
2025-07-02 04:52:33.629 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.629 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.629 else:
2025-07-02 04:52:33.629 # the synch pair is identical
2025-07-02 04:52:33.630 yield ' ' + aelt
2025-07-02 04:52:33.630
2025-07-02 04:52:33.630 # pump out diffs from after the synch point
2025-07-02 04:52:33.630 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.630
2025-07-02 04:52:33.630 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.630 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.630
2025-07-02 04:52:33.630 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.630 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.630 alo = 441, ahi = 1101
2025-07-02 04:52:33.630 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.630 blo = 441, bhi = 1101
2025-07-02 04:52:33.630
2025-07-02 04:52:33.630 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.630 g = []
2025-07-02 04:52:33.630 if alo < ahi:
2025-07-02 04:52:33.630 if blo < bhi:
2025-07-02 04:52:33.630 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.630 else:
2025-07-02 04:52:33.631 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.631 elif blo < bhi:
2025-07-02 04:52:33.631 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.631
2025-07-02 04:52:33.631 > yield from g
2025-07-02 04:52:33.631
2025-07-02 04:52:33.631 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.631 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.631
2025-07-02 04:52:33.631 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.631 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.631 alo = 441, ahi = 1101
2025-07-02 04:52:33.631 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.631 blo = 441, bhi = 1101
2025-07-02 04:52:33.631
2025-07-02 04:52:33.631 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.631 r"""
2025-07-02 04:52:33.631 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.631 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.631 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.631 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.631
2025-07-02 04:52:33.632 Example:
2025-07-02 04:52:33.632
2025-07-02 04:52:33.632 >>> d = Differ()
2025-07-02 04:52:33.632 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.632 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.632 >>> print(''.join(results), end="")
2025-07-02 04:52:33.632 - abcDefghiJkl
2025-07-02 04:52:33.632 + abcdefGhijkl
2025-07-02 04:52:33.632 """
2025-07-02 04:52:33.632
2025-07-02 04:52:33.632 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.632 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.632 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.632 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.632 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.632
2025-07-02 04:52:33.632 # search for the pair that matches best without being identical
2025-07-02 04:52:33.632 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.632 # on junk -- unless we have to)
2025-07-02 04:52:33.633 for j in range(blo, bhi):
2025-07-02 04:52:33.633 bj = b[j]
2025-07-02 04:52:33.633 cruncher.set_seq2(bj)
2025-07-02 04:52:33.633 for i in range(alo, ahi):
2025-07-02 04:52:33.633 ai = a[i]
2025-07-02 04:52:33.633 if ai == bj:
2025-07-02 04:52:33.633 if eqi is None:
2025-07-02 04:52:33.633 eqi, eqj = i, j
2025-07-02 04:52:33.633 continue
2025-07-02 04:52:33.633 cruncher.set_seq1(ai)
2025-07-02 04:52:33.633 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.633 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.633 # compares by a factor of 3.
2025-07-02 04:52:33.633 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.633 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.633 # of the computation is cached by cruncher
2025-07-02 04:52:33.633 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.633 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.633 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.633 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.633 if best_ratio < cutoff:
2025-07-02 04:52:33.633 # no non-identical "pretty close" pair
2025-07-02 04:52:33.634 if eqi is None:
2025-07-02 04:52:33.634 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.634 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.634 return
2025-07-02 04:52:33.634 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.634 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.634 else:
2025-07-02 04:52:33.634 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.634 eqi = None
2025-07-02 04:52:33.634
2025-07-02 04:52:33.634 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.634 # identical
2025-07-02 04:52:33.634
2025-07-02 04:52:33.634 # pump out diffs from before the synch point
2025-07-02 04:52:33.634 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.634
2025-07-02 04:52:33.634 # do intraline marking on the synch pair
2025-07-02 04:52:33.634 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.635 if eqi is None:
2025-07-02 04:52:33.635 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.635 atags = btags = ""
2025-07-02 04:52:33.635 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.635 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.635 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.635 if tag == 'replace':
2025-07-02 04:52:33.635 atags += '^' * la
2025-07-02 04:52:33.635 btags += '^' * lb
2025-07-02 04:52:33.635 elif tag == 'delete':
2025-07-02 04:52:33.635 atags += '-' * la
2025-07-02 04:52:33.635 elif tag == 'insert':
2025-07-02 04:52:33.635 btags += '+' * lb
2025-07-02 04:52:33.635 elif tag == 'equal':
2025-07-02 04:52:33.635 atags += ' ' * la
2025-07-02 04:52:33.635 btags += ' ' * lb
2025-07-02 04:52:33.635 else:
2025-07-02 04:52:33.635 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.635 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.635 else:
2025-07-02 04:52:33.635 # the synch pair is identical
2025-07-02 04:52:33.636 yield ' ' + aelt
2025-07-02 04:52:33.636
2025-07-02 04:52:33.636 # pump out diffs from after the synch point
2025-07-02 04:52:33.636 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.636
2025-07-02 04:52:33.636 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.636 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.636
2025-07-02 04:52:33.636 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.636 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.636 alo = 444, ahi = 1101
2025-07-02 04:52:33.636 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.636 blo = 444, bhi = 1101
2025-07-02 04:52:33.636
2025-07-02 04:52:33.636 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.636 g = []
2025-07-02 04:52:33.636 if alo < ahi:
2025-07-02 04:52:33.636 if blo < bhi:
2025-07-02 04:52:33.636 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.636 else:
2025-07-02 04:52:33.636 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.636 elif blo < bhi:
2025-07-02 04:52:33.637 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.637
2025-07-02 04:52:33.637 > yield from g
2025-07-02 04:52:33.637
2025-07-02 04:52:33.637 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.637 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.637
2025-07-02 04:52:33.637 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.637 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.637 alo = 444, ahi = 1101
2025-07-02 04:52:33.637 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.637 blo = 444, bhi = 1101
2025-07-02 04:52:33.637
2025-07-02 04:52:33.637 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.637 r"""
2025-07-02 04:52:33.637 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.637 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.637 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.637 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.638
2025-07-02 04:52:33.638 Example:
2025-07-02 04:52:33.638
2025-07-02 04:52:33.638 >>> d = Differ()
2025-07-02 04:52:33.638 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.638 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.638 >>> print(''.join(results), end="")
2025-07-02 04:52:33.638 - abcDefghiJkl
2025-07-02 04:52:33.638 + abcdefGhijkl
2025-07-02 04:52:33.638 """
2025-07-02 04:52:33.638
2025-07-02 04:52:33.638 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.638 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.638 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.638 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.638 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.638
2025-07-02 04:52:33.638 # search for the pair that matches best without being identical
2025-07-02 04:52:33.638 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.639 # on junk -- unless we have to)
2025-07-02 04:52:33.639 for j in range(blo, bhi):
2025-07-02 04:52:33.639 bj = b[j]
2025-07-02 04:52:33.639 cruncher.set_seq2(bj)
2025-07-02 04:52:33.639 for i in range(alo, ahi):
2025-07-02 04:52:33.639 ai = a[i]
2025-07-02 04:52:33.639 if ai == bj:
2025-07-02 04:52:33.639 if eqi is None:
2025-07-02 04:52:33.639 eqi, eqj = i, j
2025-07-02 04:52:33.639 continue
2025-07-02 04:52:33.639 cruncher.set_seq1(ai)
2025-07-02 04:52:33.639 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.639 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.639 # compares by a factor of 3.
2025-07-02 04:52:33.639 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.639 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.639 # of the computation is cached by cruncher
2025-07-02 04:52:33.639 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.639 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.639 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.639 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.640 if best_ratio < cutoff:
2025-07-02 04:52:33.640 # no non-identical "pretty close" pair
2025-07-02 04:52:33.640 if eqi is None:
2025-07-02 04:52:33.640 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.640 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.640 return
2025-07-02 04:52:33.640 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.640 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.640 else:
2025-07-02 04:52:33.640 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.640 eqi = None
2025-07-02 04:52:33.640
2025-07-02 04:52:33.640 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.640 # identical
2025-07-02 04:52:33.640
2025-07-02 04:52:33.640 # pump out diffs from before the synch point
2025-07-02 04:52:33.640 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.640
2025-07-02 04:52:33.640 # do intraline marking on the synch pair
2025-07-02 04:52:33.640 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.640 if eqi is None:
2025-07-02 04:52:33.641 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.641 atags = btags = ""
2025-07-02 04:52:33.641 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.641 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.641 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.641 if tag == 'replace':
2025-07-02 04:52:33.641 atags += '^' * la
2025-07-02 04:52:33.641 btags += '^' * lb
2025-07-02 04:52:33.641 elif tag == 'delete':
2025-07-02 04:52:33.641 atags += '-' * la
2025-07-02 04:52:33.641 elif tag == 'insert':
2025-07-02 04:52:33.641 btags += '+' * lb
2025-07-02 04:52:33.641 elif tag == 'equal':
2025-07-02 04:52:33.641 atags += ' ' * la
2025-07-02 04:52:33.641 btags += ' ' * lb
2025-07-02 04:52:33.641 else:
2025-07-02 04:52:33.641 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.641 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.641 else:
2025-07-02 04:52:33.641 # the synch pair is identical
2025-07-02 04:52:33.641 yield ' ' + aelt
2025-07-02 04:52:33.641
2025-07-02 04:52:33.642 # pump out diffs from after the synch point
2025-07-02 04:52:33.642 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.642
2025-07-02 04:52:33.642 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.642 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.642
2025-07-02 04:52:33.642 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.642 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.642 alo = 445, ahi = 1101
2025-07-02 04:52:33.642 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.642 blo = 445, bhi = 1101
2025-07-02 04:52:33.642
2025-07-02 04:52:33.642 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.642 g = []
2025-07-02 04:52:33.642 if alo < ahi:
2025-07-02 04:52:33.642 if blo < bhi:
2025-07-02 04:52:33.642 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.642 else:
2025-07-02 04:52:33.642 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.643 elif blo < bhi:
2025-07-02 04:52:33.643 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.643
2025-07-02 04:52:33.643 > yield from g
2025-07-02 04:52:33.643
2025-07-02 04:52:33.643 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.643 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.643
2025-07-02 04:52:33.643 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.643 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.643 alo = 445, ahi = 1101
2025-07-02 04:52:33.643 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.643 blo = 445, bhi = 1101
2025-07-02 04:52:33.643
2025-07-02 04:52:33.643 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.643 r"""
2025-07-02 04:52:33.643 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.643 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.643 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.643 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.644
2025-07-02 04:52:33.644 Example:
2025-07-02 04:52:33.644
2025-07-02 04:52:33.644 >>> d = Differ()
2025-07-02 04:52:33.644 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.644 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.644 >>> print(''.join(results), end="")
2025-07-02 04:52:33.644 - abcDefghiJkl
2025-07-02 04:52:33.644 + abcdefGhijkl
2025-07-02 04:52:33.644 """
2025-07-02 04:52:33.644
2025-07-02 04:52:33.644 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.644 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.644 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.644 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.644 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.644
2025-07-02 04:52:33.644 # search for the pair that matches best without being identical
2025-07-02 04:52:33.644 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.644 # on junk -- unless we have to)
2025-07-02 04:52:33.645 for j in range(blo, bhi):
2025-07-02 04:52:33.645 bj = b[j]
2025-07-02 04:52:33.645 cruncher.set_seq2(bj)
2025-07-02 04:52:33.645 for i in range(alo, ahi):
2025-07-02 04:52:33.645 ai = a[i]
2025-07-02 04:52:33.645 if ai == bj:
2025-07-02 04:52:33.645 if eqi is None:
2025-07-02 04:52:33.645 eqi, eqj = i, j
2025-07-02 04:52:33.645 continue
2025-07-02 04:52:33.645 cruncher.set_seq1(ai)
2025-07-02 04:52:33.645 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.645 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.645 # compares by a factor of 3.
2025-07-02 04:52:33.645 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.645 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.645 # of the computation is cached by cruncher
2025-07-02 04:52:33.645 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.645 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.645 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.646 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.646 if best_ratio < cutoff:
2025-07-02 04:52:33.646 # no non-identical "pretty close" pair
2025-07-02 04:52:33.646 if eqi is None:
2025-07-02 04:52:33.646 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.646 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.646 return
2025-07-02 04:52:33.646 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.646 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.646 else:
2025-07-02 04:52:33.646 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.646 eqi = None
2025-07-02 04:52:33.646
2025-07-02 04:52:33.646 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.646 # identical
2025-07-02 04:52:33.646
2025-07-02 04:52:33.646 # pump out diffs from before the synch point
2025-07-02 04:52:33.646 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.646
2025-07-02 04:52:33.646 # do intraline marking on the synch pair
2025-07-02 04:52:33.646 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.647 if eqi is None:
2025-07-02 04:52:33.647 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.647 atags = btags = ""
2025-07-02 04:52:33.647 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.647 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.647 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.647 if tag == 'replace':
2025-07-02 04:52:33.647 atags += '^' * la
2025-07-02 04:52:33.647 btags += '^' * lb
2025-07-02 04:52:33.647 elif tag == 'delete':
2025-07-02 04:52:33.647 atags += '-' * la
2025-07-02 04:52:33.647 elif tag == 'insert':
2025-07-02 04:52:33.647 btags += '+' * lb
2025-07-02 04:52:33.647 elif tag == 'equal':
2025-07-02 04:52:33.647 atags += ' ' * la
2025-07-02 04:52:33.647 btags += ' ' * lb
2025-07-02 04:52:33.647 else:
2025-07-02 04:52:33.647 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.647 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.647 else:
2025-07-02 04:52:33.648 # the synch pair is identical
2025-07-02 04:52:33.648 yield ' ' + aelt
2025-07-02 04:52:33.648
2025-07-02 04:52:33.648 # pump out diffs from after the synch point
2025-07-02 04:52:33.648 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.648
2025-07-02 04:52:33.648 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.648 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.648
2025-07-02 04:52:33.648 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.648 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.648 alo = 446, ahi = 1101
2025-07-02 04:52:33.648 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.648 blo = 446, bhi = 1101
2025-07-02 04:52:33.648
2025-07-02 04:52:33.648 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.648 g = []
2025-07-02 04:52:33.648 if alo < ahi:
2025-07-02 04:52:33.648 if blo < bhi:
2025-07-02 04:52:33.648 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.648 else:
2025-07-02 04:52:33.649 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.649 elif blo < bhi:
2025-07-02 04:52:33.649 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.649
2025-07-02 04:52:33.649 > yield from g
2025-07-02 04:52:33.649
2025-07-02 04:52:33.649 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.649 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.649
2025-07-02 04:52:33.649 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.649 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.649 alo = 446, ahi = 1101
2025-07-02 04:52:33.649 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.649 blo = 446, bhi = 1101
2025-07-02 04:52:33.649
2025-07-02 04:52:33.649 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.649 r"""
2025-07-02 04:52:33.649 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.649 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.649 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.649 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.650
2025-07-02 04:52:33.650 Example:
2025-07-02 04:52:33.650
2025-07-02 04:52:33.650 >>> d = Differ()
2025-07-02 04:52:33.650 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.650 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.650 >>> print(''.join(results), end="")
2025-07-02 04:52:33.650 - abcDefghiJkl
2025-07-02 04:52:33.650 + abcdefGhijkl
2025-07-02 04:52:33.650 """
2025-07-02 04:52:33.650
2025-07-02 04:52:33.650 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.650 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.650 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.650 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.650 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.650
2025-07-02 04:52:33.651 # search for the pair that matches best without being identical
2025-07-02 04:52:33.651 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.651 # on junk -- unless we have to)
2025-07-02 04:52:33.651 for j in range(blo, bhi):
2025-07-02 04:52:33.651 bj = b[j]
2025-07-02 04:52:33.651 cruncher.set_seq2(bj)
2025-07-02 04:52:33.651 for i in range(alo, ahi):
2025-07-02 04:52:33.651 ai = a[i]
2025-07-02 04:52:33.651 if ai == bj:
2025-07-02 04:52:33.651 if eqi is None:
2025-07-02 04:52:33.651 eqi, eqj = i, j
2025-07-02 04:52:33.651 continue
2025-07-02 04:52:33.651 cruncher.set_seq1(ai)
2025-07-02 04:52:33.651 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.651 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.651 # compares by a factor of 3.
2025-07-02 04:52:33.651 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.651 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.651 # of the computation is cached by cruncher
2025-07-02 04:52:33.652 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.652 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.652 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.652 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.652 if best_ratio < cutoff:
2025-07-02 04:52:33.652 # no non-identical "pretty close" pair
2025-07-02 04:52:33.652 if eqi is None:
2025-07-02 04:52:33.652 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.652 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.652 return
2025-07-02 04:52:33.652 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.652 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.652 else:
2025-07-02 04:52:33.652 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.652 eqi = None
2025-07-02 04:52:33.652
2025-07-02 04:52:33.652 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.652 # identical
2025-07-02 04:52:33.652
2025-07-02 04:52:33.652 # pump out diffs from before the synch point
2025-07-02 04:52:33.652 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.652
2025-07-02 04:52:33.653 # do intraline marking on the synch pair
2025-07-02 04:52:33.653 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.653 if eqi is None:
2025-07-02 04:52:33.653 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.653 atags = btags = ""
2025-07-02 04:52:33.653 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.653 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.653 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.653 if tag == 'replace':
2025-07-02 04:52:33.653 atags += '^' * la
2025-07-02 04:52:33.653 btags += '^' * lb
2025-07-02 04:52:33.653 elif tag == 'delete':
2025-07-02 04:52:33.653 atags += '-' * la
2025-07-02 04:52:33.653 elif tag == 'insert':
2025-07-02 04:52:33.653 btags += '+' * lb
2025-07-02 04:52:33.653 elif tag == 'equal':
2025-07-02 04:52:33.653 atags += ' ' * la
2025-07-02 04:52:33.653 btags += ' ' * lb
2025-07-02 04:52:33.653 else:
2025-07-02 04:52:33.653 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.653 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.654 else:
2025-07-02 04:52:33.654 # the synch pair is identical
2025-07-02 04:52:33.654 yield ' ' + aelt
2025-07-02 04:52:33.654
2025-07-02 04:52:33.654 # pump out diffs from after the synch point
2025-07-02 04:52:33.654 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.654
2025-07-02 04:52:33.654 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.654 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.654
2025-07-02 04:52:33.654 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.654 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.654 alo = 447, ahi = 1101
2025-07-02 04:52:33.654 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.654 blo = 447, bhi = 1101
2025-07-02 04:52:33.654
2025-07-02 04:52:33.654 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.654 g = []
2025-07-02 04:52:33.655 if alo < ahi:
2025-07-02 04:52:33.655 if blo < bhi:
2025-07-02 04:52:33.655 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.655 else:
2025-07-02 04:52:33.655 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.655 elif blo < bhi:
2025-07-02 04:52:33.655 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.655
2025-07-02 04:52:33.655 > yield from g
2025-07-02 04:52:33.655
2025-07-02 04:52:33.655 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.655 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.655
2025-07-02 04:52:33.655 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.655 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.655 alo = 447, ahi = 1101
2025-07-02 04:52:33.655 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.655 blo = 447, bhi = 1101
2025-07-02 04:52:33.655
2025-07-02 04:52:33.655 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.656 r"""
2025-07-02 04:52:33.656 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.656 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.656 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.656 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.656
2025-07-02 04:52:33.656 Example:
2025-07-02 04:52:33.656
2025-07-02 04:52:33.656 >>> d = Differ()
2025-07-02 04:52:33.656 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.656 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.656 >>> print(''.join(results), end="")
2025-07-02 04:52:33.656 - abcDefghiJkl
2025-07-02 04:52:33.656 + abcdefGhijkl
2025-07-02 04:52:33.656 """
2025-07-02 04:52:33.656
2025-07-02 04:52:33.656 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.656 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.656 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.656 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.657 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.657
2025-07-02 04:52:33.657 # search for the pair that matches best without being identical
2025-07-02 04:52:33.657 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.657 # on junk -- unless we have to)
2025-07-02 04:52:33.657 for j in range(blo, bhi):
2025-07-02 04:52:33.657 bj = b[j]
2025-07-02 04:52:33.657 cruncher.set_seq2(bj)
2025-07-02 04:52:33.657 for i in range(alo, ahi):
2025-07-02 04:52:33.657 ai = a[i]
2025-07-02 04:52:33.657 if ai == bj:
2025-07-02 04:52:33.657 if eqi is None:
2025-07-02 04:52:33.657 eqi, eqj = i, j
2025-07-02 04:52:33.657 continue
2025-07-02 04:52:33.657 cruncher.set_seq1(ai)
2025-07-02 04:52:33.657 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.657 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.657 # compares by a factor of 3.
2025-07-02 04:52:33.657 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.657 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.658 # of the computation is cached by cruncher
2025-07-02 04:52:33.658 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.658 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.658 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.658 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.658 if best_ratio < cutoff:
2025-07-02 04:52:33.658 # no non-identical "pretty close" pair
2025-07-02 04:52:33.658 if eqi is None:
2025-07-02 04:52:33.658 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.658 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.658 return
2025-07-02 04:52:33.658 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.658 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.658 else:
2025-07-02 04:52:33.658 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.658 eqi = None
2025-07-02 04:52:33.658
2025-07-02 04:52:33.658 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.658 # identical
2025-07-02 04:52:33.658
2025-07-02 04:52:33.658 # pump out diffs from before the synch point
2025-07-02 04:52:33.658 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.659
2025-07-02 04:52:33.659 # do intraline marking on the synch pair
2025-07-02 04:52:33.659 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.659 if eqi is None:
2025-07-02 04:52:33.659 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.659 atags = btags = ""
2025-07-02 04:52:33.659 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.659 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.659 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.659 if tag == 'replace':
2025-07-02 04:52:33.659 atags += '^' * la
2025-07-02 04:52:33.659 btags += '^' * lb
2025-07-02 04:52:33.659 elif tag == 'delete':
2025-07-02 04:52:33.659 atags += '-' * la
2025-07-02 04:52:33.659 elif tag == 'insert':
2025-07-02 04:52:33.659 btags += '+' * lb
2025-07-02 04:52:33.659 elif tag == 'equal':
2025-07-02 04:52:33.659 atags += ' ' * la
2025-07-02 04:52:33.659 btags += ' ' * lb
2025-07-02 04:52:33.659 else:
2025-07-02 04:52:33.659 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.660 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.660 else:
2025-07-02 04:52:33.660 # the synch pair is identical
2025-07-02 04:52:33.660 yield ' ' + aelt
2025-07-02 04:52:33.660
2025-07-02 04:52:33.660 # pump out diffs from after the synch point
2025-07-02 04:52:33.660 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.660
2025-07-02 04:52:33.660 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.660 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.660
2025-07-02 04:52:33.660 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.660 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.660 alo = 448, ahi = 1101
2025-07-02 04:52:33.660 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.660 blo = 448, bhi = 1101
2025-07-02 04:52:33.660
2025-07-02 04:52:33.660 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.660 g = []
2025-07-02 04:52:33.660 if alo < ahi:
2025-07-02 04:52:33.660 if blo < bhi:
2025-07-02 04:52:33.661 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.661 else:
2025-07-02 04:52:33.661 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.661 elif blo < bhi:
2025-07-02 04:52:33.661 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.661
2025-07-02 04:52:33.661 > yield from g
2025-07-02 04:52:33.661
2025-07-02 04:52:33.661 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.661 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.661
2025-07-02 04:52:33.661 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.661 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.661 alo = 448, ahi = 1101
2025-07-02 04:52:33.661 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.661 blo = 448, bhi = 1101
2025-07-02 04:52:33.661
2025-07-02 04:52:33.661 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.661 r"""
2025-07-02 04:52:33.661 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.661 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.662 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.662 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.662
2025-07-02 04:52:33.662 Example:
2025-07-02 04:52:33.662
2025-07-02 04:52:33.662 >>> d = Differ()
2025-07-02 04:52:33.662 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.662 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.662 >>> print(''.join(results), end="")
2025-07-02 04:52:33.662 - abcDefghiJkl
2025-07-02 04:52:33.662 + abcdefGhijkl
2025-07-02 04:52:33.662 """
2025-07-02 04:52:33.662
2025-07-02 04:52:33.662 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.662 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.662 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.662 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.663 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.663
2025-07-02 04:52:33.663 # search for the pair that matches best without being identical
2025-07-02 04:52:33.663 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.663 # on junk -- unless we have to)
2025-07-02 04:52:33.663 for j in range(blo, bhi):
2025-07-02 04:52:33.663 bj = b[j]
2025-07-02 04:52:33.663 cruncher.set_seq2(bj)
2025-07-02 04:52:33.663 for i in range(alo, ahi):
2025-07-02 04:52:33.663 ai = a[i]
2025-07-02 04:52:33.663 if ai == bj:
2025-07-02 04:52:33.663 if eqi is None:
2025-07-02 04:52:33.663 eqi, eqj = i, j
2025-07-02 04:52:33.663 continue
2025-07-02 04:52:33.663 cruncher.set_seq1(ai)
2025-07-02 04:52:33.663 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.663 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.663 # compares by a factor of 3.
2025-07-02 04:52:33.663 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.663 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.664 # of the computation is cached by cruncher
2025-07-02 04:52:33.664 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.664 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.664 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.664 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.664 if best_ratio < cutoff:
2025-07-02 04:52:33.664 # no non-identical "pretty close" pair
2025-07-02 04:52:33.664 if eqi is None:
2025-07-02 04:52:33.664 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.664 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.664 return
2025-07-02 04:52:33.664 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.664 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.664 else:
2025-07-02 04:52:33.664 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.664 eqi = None
2025-07-02 04:52:33.664
2025-07-02 04:52:33.664 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.664 # identical
2025-07-02 04:52:33.664
2025-07-02 04:52:33.664 # pump out diffs from before the synch point
2025-07-02 04:52:33.665 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.665
2025-07-02 04:52:33.665 # do intraline marking on the synch pair
2025-07-02 04:52:33.665 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.665 if eqi is None:
2025-07-02 04:52:33.665 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.665 atags = btags = ""
2025-07-02 04:52:33.665 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.665 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.665 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.665 if tag == 'replace':
2025-07-02 04:52:33.665 atags += '^' * la
2025-07-02 04:52:33.665 btags += '^' * lb
2025-07-02 04:52:33.665 elif tag == 'delete':
2025-07-02 04:52:33.665 atags += '-' * la
2025-07-02 04:52:33.665 elif tag == 'insert':
2025-07-02 04:52:33.665 btags += '+' * lb
2025-07-02 04:52:33.665 elif tag == 'equal':
2025-07-02 04:52:33.665 atags += ' ' * la
2025-07-02 04:52:33.665 btags += ' ' * lb
2025-07-02 04:52:33.665 else:
2025-07-02 04:52:33.666 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.666 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.666 else:
2025-07-02 04:52:33.666 # the synch pair is identical
2025-07-02 04:52:33.666 yield ' ' + aelt
2025-07-02 04:52:33.666
2025-07-02 04:52:33.666 # pump out diffs from after the synch point
2025-07-02 04:52:33.666 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.666
2025-07-02 04:52:33.666 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.666 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.666
2025-07-02 04:52:33.666 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.666 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.666 alo = 449, ahi = 1101
2025-07-02 04:52:33.666 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.666 blo = 449, bhi = 1101
2025-07-02 04:52:33.666
2025-07-02 04:52:33.666 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.667 g = []
2025-07-02 04:52:33.667 if alo < ahi:
2025-07-02 04:52:33.667 if blo < bhi:
2025-07-02 04:52:33.667 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.667 else:
2025-07-02 04:52:33.667 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.667 elif blo < bhi:
2025-07-02 04:52:33.667 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.667
2025-07-02 04:52:33.667 > yield from g
2025-07-02 04:52:33.667
2025-07-02 04:52:33.667 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.667 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.667
2025-07-02 04:52:33.667 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.667 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.667 alo = 449, ahi = 1101
2025-07-02 04:52:33.667 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.667 blo = 449, bhi = 1101
2025-07-02 04:52:33.667
2025-07-02 04:52:33.668 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.668 r"""
2025-07-02 04:52:33.668 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.668 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.668 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.668 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.668
2025-07-02 04:52:33.668 Example:
2025-07-02 04:52:33.668
2025-07-02 04:52:33.668 >>> d = Differ()
2025-07-02 04:52:33.668 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.668 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.668 >>> print(''.join(results), end="")
2025-07-02 04:52:33.668 - abcDefghiJkl
2025-07-02 04:52:33.668 + abcdefGhijkl
2025-07-02 04:52:33.668 """
2025-07-02 04:52:33.668
2025-07-02 04:52:33.668 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.668 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.669 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.669 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.669 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.669
2025-07-02 04:52:33.669 # search for the pair that matches best without being identical
2025-07-02 04:52:33.669 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.669 # on junk -- unless we have to)
2025-07-02 04:52:33.669 for j in range(blo, bhi):
2025-07-02 04:52:33.669 bj = b[j]
2025-07-02 04:52:33.669 cruncher.set_seq2(bj)
2025-07-02 04:52:33.669 for i in range(alo, ahi):
2025-07-02 04:52:33.669 ai = a[i]
2025-07-02 04:52:33.669 if ai == bj:
2025-07-02 04:52:33.669 if eqi is None:
2025-07-02 04:52:33.669 eqi, eqj = i, j
2025-07-02 04:52:33.669 continue
2025-07-02 04:52:33.669 cruncher.set_seq1(ai)
2025-07-02 04:52:33.669 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.669 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.669 # compares by a factor of 3.
2025-07-02 04:52:33.669 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.670 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.670 # of the computation is cached by cruncher
2025-07-02 04:52:33.670 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.670 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.670 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.670 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.670 if best_ratio < cutoff:
2025-07-02 04:52:33.670 # no non-identical "pretty close" pair
2025-07-02 04:52:33.670 if eqi is None:
2025-07-02 04:52:33.670 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.670 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.670 return
2025-07-02 04:52:33.670 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.670 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.670 else:
2025-07-02 04:52:33.670 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.670 eqi = None
2025-07-02 04:52:33.670
2025-07-02 04:52:33.670 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.670 # identical
2025-07-02 04:52:33.671
2025-07-02 04:52:33.671 # pump out diffs from before the synch point
2025-07-02 04:52:33.671 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.671
2025-07-02 04:52:33.671 # do intraline marking on the synch pair
2025-07-02 04:52:33.671 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.671 if eqi is None:
2025-07-02 04:52:33.671 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.671 atags = btags = ""
2025-07-02 04:52:33.671 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.671 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.671 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.671 if tag == 'replace':
2025-07-02 04:52:33.671 atags += '^' * la
2025-07-02 04:52:33.671 btags += '^' * lb
2025-07-02 04:52:33.671 elif tag == 'delete':
2025-07-02 04:52:33.671 atags += '-' * la
2025-07-02 04:52:33.671 elif tag == 'insert':
2025-07-02 04:52:33.671 btags += '+' * lb
2025-07-02 04:52:33.671 elif tag == 'equal':
2025-07-02 04:52:33.672 atags += ' ' * la
2025-07-02 04:52:33.672 btags += ' ' * lb
2025-07-02 04:52:33.672 else:
2025-07-02 04:52:33.672 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.672 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.672 else:
2025-07-02 04:52:33.672 # the synch pair is identical
2025-07-02 04:52:33.672 yield ' ' + aelt
2025-07-02 04:52:33.672
2025-07-02 04:52:33.672 # pump out diffs from after the synch point
2025-07-02 04:52:33.672 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.672
2025-07-02 04:52:33.672 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.672 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.672
2025-07-02 04:52:33.672 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.672 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.672 alo = 450, ahi = 1101
2025-07-02 04:52:33.672 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.672 blo = 450, bhi = 1101
2025-07-02 04:52:33.673
2025-07-02 04:52:33.673 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.673 g = []
2025-07-02 04:52:33.673 if alo < ahi:
2025-07-02 04:52:33.673 if blo < bhi:
2025-07-02 04:52:33.673 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.673 else:
2025-07-02 04:52:33.673 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.673 elif blo < bhi:
2025-07-02 04:52:33.673 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.673
2025-07-02 04:52:33.673 > yield from g
2025-07-02 04:52:33.673
2025-07-02 04:52:33.673 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.673 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.673
2025-07-02 04:52:33.673 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.673 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.673 alo = 450, ahi = 1101
2025-07-02 04:52:33.673 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.673 blo = 450, bhi = 1101
2025-07-02 04:52:33.674
2025-07-02 04:52:33.674 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.674 r"""
2025-07-02 04:52:33.674 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.674 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.674 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.674 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.674
2025-07-02 04:52:33.674 Example:
2025-07-02 04:52:33.674
2025-07-02 04:52:33.674 >>> d = Differ()
2025-07-02 04:52:33.674 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.674 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.674 >>> print(''.join(results), end="")
2025-07-02 04:52:33.674 - abcDefghiJkl
2025-07-02 04:52:33.674 + abcdefGhijkl
2025-07-02 04:52:33.674 """
2025-07-02 04:52:33.674
2025-07-02 04:52:33.674 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.675 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.675 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.675 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.675 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.675
2025-07-02 04:52:33.675 # search for the pair that matches best without being identical
2025-07-02 04:52:33.675 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.675 # on junk -- unless we have to)
2025-07-02 04:52:33.675 for j in range(blo, bhi):
2025-07-02 04:52:33.675 bj = b[j]
2025-07-02 04:52:33.675 cruncher.set_seq2(bj)
2025-07-02 04:52:33.675 for i in range(alo, ahi):
2025-07-02 04:52:33.675 ai = a[i]
2025-07-02 04:52:33.675 if ai == bj:
2025-07-02 04:52:33.675 if eqi is None:
2025-07-02 04:52:33.675 eqi, eqj = i, j
2025-07-02 04:52:33.675 continue
2025-07-02 04:52:33.675 cruncher.set_seq1(ai)
2025-07-02 04:52:33.675 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.675 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.675 # compares by a factor of 3.
2025-07-02 04:52:33.675 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.676 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.676 # of the computation is cached by cruncher
2025-07-02 04:52:33.676 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.676 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.676 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.676 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.676 if best_ratio < cutoff:
2025-07-02 04:52:33.676 # no non-identical "pretty close" pair
2025-07-02 04:52:33.676 if eqi is None:
2025-07-02 04:52:33.676 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.676 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.676 return
2025-07-02 04:52:33.676 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.676 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.676 else:
2025-07-02 04:52:33.676 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.676 eqi = None
2025-07-02 04:52:33.676
2025-07-02 04:52:33.676 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.676 # identical
2025-07-02 04:52:33.677
2025-07-02 04:52:33.677 # pump out diffs from before the synch point
2025-07-02 04:52:33.677 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.677
2025-07-02 04:52:33.677 # do intraline marking on the synch pair
2025-07-02 04:52:33.677 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.677 if eqi is None:
2025-07-02 04:52:33.677 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.677 atags = btags = ""
2025-07-02 04:52:33.677 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.677 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.677 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.677 if tag == 'replace':
2025-07-02 04:52:33.677 atags += '^' * la
2025-07-02 04:52:33.677 btags += '^' * lb
2025-07-02 04:52:33.677 elif tag == 'delete':
2025-07-02 04:52:33.677 atags += '-' * la
2025-07-02 04:52:33.677 elif tag == 'insert':
2025-07-02 04:52:33.677 btags += '+' * lb
2025-07-02 04:52:33.677 elif tag == 'equal':
2025-07-02 04:52:33.677 atags += ' ' * la
2025-07-02 04:52:33.677 btags += ' ' * lb
2025-07-02 04:52:33.678 else:
2025-07-02 04:52:33.678 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.678 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.678 else:
2025-07-02 04:52:33.678 # the synch pair is identical
2025-07-02 04:52:33.678 yield ' ' + aelt
2025-07-02 04:52:33.678
2025-07-02 04:52:33.678 # pump out diffs from after the synch point
2025-07-02 04:52:33.678 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.678
2025-07-02 04:52:33.678 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.678 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.678
2025-07-02 04:52:33.678 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.678 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.678 alo = 451, ahi = 1101
2025-07-02 04:52:33.678 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.678 blo = 451, bhi = 1101
2025-07-02 04:52:33.678
2025-07-02 04:52:33.678 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.678 g = []
2025-07-02 04:52:33.679 if alo < ahi:
2025-07-02 04:52:33.679 if blo < bhi:
2025-07-02 04:52:33.679 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.679 else:
2025-07-02 04:52:33.679 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.679 elif blo < bhi:
2025-07-02 04:52:33.679 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.679
2025-07-02 04:52:33.679 > yield from g
2025-07-02 04:52:33.679
2025-07-02 04:52:33.679 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.679 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.679
2025-07-02 04:52:33.679 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.679 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.679 alo = 451, ahi = 1101
2025-07-02 04:52:33.679 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.679 blo = 451, bhi = 1101
2025-07-02 04:52:33.679
2025-07-02 04:52:33.680 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.680 r"""
2025-07-02 04:52:33.680 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.680 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.680 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.680 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.680
2025-07-02 04:52:33.680 Example:
2025-07-02 04:52:33.680
2025-07-02 04:52:33.680 >>> d = Differ()
2025-07-02 04:52:33.680 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.680 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.680 >>> print(''.join(results), end="")
2025-07-02 04:52:33.680 - abcDefghiJkl
2025-07-02 04:52:33.680 + abcdefGhijkl
2025-07-02 04:52:33.680 """
2025-07-02 04:52:33.680
2025-07-02 04:52:33.680 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.681 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.681 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.681 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.681 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.681
2025-07-02 04:52:33.681 # search for the pair that matches best without being identical
2025-07-02 04:52:33.681 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.681 # on junk -- unless we have to)
2025-07-02 04:52:33.681 for j in range(blo, bhi):
2025-07-02 04:52:33.681 bj = b[j]
2025-07-02 04:52:33.681 cruncher.set_seq2(bj)
2025-07-02 04:52:33.681 for i in range(alo, ahi):
2025-07-02 04:52:33.681 ai = a[i]
2025-07-02 04:52:33.681 if ai == bj:
2025-07-02 04:52:33.681 if eqi is None:
2025-07-02 04:52:33.681 eqi, eqj = i, j
2025-07-02 04:52:33.681 continue
2025-07-02 04:52:33.681 cruncher.set_seq1(ai)
2025-07-02 04:52:33.681 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.681 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.681 # compares by a factor of 3.
2025-07-02 04:52:33.681 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.682 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.682 # of the computation is cached by cruncher
2025-07-02 04:52:33.682 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.682 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.682 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.682 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.682 if best_ratio < cutoff:
2025-07-02 04:52:33.682 # no non-identical "pretty close" pair
2025-07-02 04:52:33.682 if eqi is None:
2025-07-02 04:52:33.682 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.682 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.682 return
2025-07-02 04:52:33.682 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.682 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.682 else:
2025-07-02 04:52:33.682 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.682 eqi = None
2025-07-02 04:52:33.682
2025-07-02 04:52:33.682 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.683 # identical
2025-07-02 04:52:33.683
2025-07-02 04:52:33.683 # pump out diffs from before the synch point
2025-07-02 04:52:33.683 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.683
2025-07-02 04:52:33.683 # do intraline marking on the synch pair
2025-07-02 04:52:33.683 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.683 if eqi is None:
2025-07-02 04:52:33.683 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.683 atags = btags = ""
2025-07-02 04:52:33.683 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.683 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.683 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.683 if tag == 'replace':
2025-07-02 04:52:33.683 atags += '^' * la
2025-07-02 04:52:33.683 btags += '^' * lb
2025-07-02 04:52:33.683 elif tag == 'delete':
2025-07-02 04:52:33.683 atags += '-' * la
2025-07-02 04:52:33.683 elif tag == 'insert':
2025-07-02 04:52:33.683 btags += '+' * lb
2025-07-02 04:52:33.684 elif tag == 'equal':
2025-07-02 04:52:33.684 atags += ' ' * la
2025-07-02 04:52:33.684 btags += ' ' * lb
2025-07-02 04:52:33.684 else:
2025-07-02 04:52:33.684 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.684 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.684 else:
2025-07-02 04:52:33.684 # the synch pair is identical
2025-07-02 04:52:33.684 yield ' ' + aelt
2025-07-02 04:52:33.684
2025-07-02 04:52:33.684 # pump out diffs from after the synch point
2025-07-02 04:52:33.684 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.684
2025-07-02 04:52:33.684 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.684 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.684
2025-07-02 04:52:33.684 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.684 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.684 alo = 452, ahi = 1101
2025-07-02 04:52:33.684 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.684 blo = 452, bhi = 1101
2025-07-02 04:52:33.685
2025-07-02 04:52:33.685 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.685 g = []
2025-07-02 04:52:33.685 if alo < ahi:
2025-07-02 04:52:33.685 if blo < bhi:
2025-07-02 04:52:33.685 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.685 else:
2025-07-02 04:52:33.685 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.685 elif blo < bhi:
2025-07-02 04:52:33.685 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.685
2025-07-02 04:52:33.685 > yield from g
2025-07-02 04:52:33.685
2025-07-02 04:52:33.685 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.685 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.685
2025-07-02 04:52:33.685 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.685 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.685 alo = 452, ahi = 1101
2025-07-02 04:52:33.685 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.686 blo = 452, bhi = 1101
2025-07-02 04:52:33.686
2025-07-02 04:52:33.686 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.686 r"""
2025-07-02 04:52:33.686 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.686 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.686 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.686 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.686
2025-07-02 04:52:33.686 Example:
2025-07-02 04:52:33.686
2025-07-02 04:52:33.686 >>> d = Differ()
2025-07-02 04:52:33.686 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.686 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.686 >>> print(''.join(results), end="")
2025-07-02 04:52:33.686 - abcDefghiJkl
2025-07-02 04:52:33.686 + abcdefGhijkl
2025-07-02 04:52:33.686 """
2025-07-02 04:52:33.686
2025-07-02 04:52:33.686 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.687 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.687 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.687 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.687 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.687
2025-07-02 04:52:33.687 # search for the pair that matches best without being identical
2025-07-02 04:52:33.687 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.687 # on junk -- unless we have to)
2025-07-02 04:52:33.687 for j in range(blo, bhi):
2025-07-02 04:52:33.687 bj = b[j]
2025-07-02 04:52:33.687 cruncher.set_seq2(bj)
2025-07-02 04:52:33.687 for i in range(alo, ahi):
2025-07-02 04:52:33.687 ai = a[i]
2025-07-02 04:52:33.687 if ai == bj:
2025-07-02 04:52:33.687 if eqi is None:
2025-07-02 04:52:33.687 eqi, eqj = i, j
2025-07-02 04:52:33.687 continue
2025-07-02 04:52:33.687 cruncher.set_seq1(ai)
2025-07-02 04:52:33.687 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.688 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.688 # compares by a factor of 3.
2025-07-02 04:52:33.688 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.688 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.688 # of the computation is cached by cruncher
2025-07-02 04:52:33.688 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.688 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.688 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.688 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.688 if best_ratio < cutoff:
2025-07-02 04:52:33.688 # no non-identical "pretty close" pair
2025-07-02 04:52:33.688 if eqi is None:
2025-07-02 04:52:33.688 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.688 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.688 return
2025-07-02 04:52:33.688 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.688 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.688 else:
2025-07-02 04:52:33.688 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.688 eqi = None
2025-07-02 04:52:33.689
2025-07-02 04:52:33.689 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.689 # identical
2025-07-02 04:52:33.689
2025-07-02 04:52:33.689 # pump out diffs from before the synch point
2025-07-02 04:52:33.689 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.689
2025-07-02 04:52:33.689 # do intraline marking on the synch pair
2025-07-02 04:52:33.689 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.689 if eqi is None:
2025-07-02 04:52:33.689 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.689 atags = btags = ""
2025-07-02 04:52:33.689 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.689 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.689 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.689 if tag == 'replace':
2025-07-02 04:52:33.689 atags += '^' * la
2025-07-02 04:52:33.689 btags += '^' * lb
2025-07-02 04:52:33.689 elif tag == 'delete':
2025-07-02 04:52:33.689 atags += '-' * la
2025-07-02 04:52:33.689 elif tag == 'insert':
2025-07-02 04:52:33.690 btags += '+' * lb
2025-07-02 04:52:33.690 elif tag == 'equal':
2025-07-02 04:52:33.690 atags += ' ' * la
2025-07-02 04:52:33.690 btags += ' ' * lb
2025-07-02 04:52:33.690 else:
2025-07-02 04:52:33.690 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.690 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.690 else:
2025-07-02 04:52:33.690 # the synch pair is identical
2025-07-02 04:52:33.690 yield ' ' + aelt
2025-07-02 04:52:33.690
2025-07-02 04:52:33.690 # pump out diffs from after the synch point
2025-07-02 04:52:33.690 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.690
2025-07-02 04:52:33.690 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.690 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.690
2025-07-02 04:52:33.690 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.690 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.690 alo = 453, ahi = 1101
2025-07-02 04:52:33.690 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.691 blo = 453, bhi = 1101
2025-07-02 04:52:33.691
2025-07-02 04:52:33.691 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.691 g = []
2025-07-02 04:52:33.691 if alo < ahi:
2025-07-02 04:52:33.691 if blo < bhi:
2025-07-02 04:52:33.691 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.691 else:
2025-07-02 04:52:33.691 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.691 elif blo < bhi:
2025-07-02 04:52:33.691 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.691
2025-07-02 04:52:33.691 > yield from g
2025-07-02 04:52:33.691
2025-07-02 04:52:33.691 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.691 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.691
2025-07-02 04:52:33.691 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.691 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.691 alo = 453, ahi = 1101
2025-07-02 04:52:33.691 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.692 blo = 453, bhi = 1101
2025-07-02 04:52:33.692
2025-07-02 04:52:33.692 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.692 r"""
2025-07-02 04:52:33.692 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.692 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.692 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.692 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.692
2025-07-02 04:52:33.692 Example:
2025-07-02 04:52:33.692
2025-07-02 04:52:33.692 >>> d = Differ()
2025-07-02 04:52:33.692 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.692 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.692 >>> print(''.join(results), end="")
2025-07-02 04:52:33.692 - abcDefghiJkl
2025-07-02 04:52:33.692 + abcdefGhijkl
2025-07-02 04:52:33.692 """
2025-07-02 04:52:33.692
2025-07-02 04:52:33.692 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.693 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.693 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.693 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.693 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.693
2025-07-02 04:52:33.693 # search for the pair that matches best without being identical
2025-07-02 04:52:33.693 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.693 # on junk -- unless we have to)
2025-07-02 04:52:33.693 for j in range(blo, bhi):
2025-07-02 04:52:33.693 bj = b[j]
2025-07-02 04:52:33.693 cruncher.set_seq2(bj)
2025-07-02 04:52:33.693 for i in range(alo, ahi):
2025-07-02 04:52:33.693 ai = a[i]
2025-07-02 04:52:33.693 if ai == bj:
2025-07-02 04:52:33.693 if eqi is None:
2025-07-02 04:52:33.693 eqi, eqj = i, j
2025-07-02 04:52:33.693 continue
2025-07-02 04:52:33.693 cruncher.set_seq1(ai)
2025-07-02 04:52:33.693 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.693 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.693 # compares by a factor of 3.
2025-07-02 04:52:33.694 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.694 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.694 # of the computation is cached by cruncher
2025-07-02 04:52:33.694 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.694 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.694 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.694 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.694 if best_ratio < cutoff:
2025-07-02 04:52:33.694 # no non-identical "pretty close" pair
2025-07-02 04:52:33.694 if eqi is None:
2025-07-02 04:52:33.694 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.694 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.694 return
2025-07-02 04:52:33.694 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.694 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.694 else:
2025-07-02 04:52:33.694 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.694 eqi = None
2025-07-02 04:52:33.694
2025-07-02 04:52:33.694 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.694 # identical
2025-07-02 04:52:33.695
2025-07-02 04:52:33.695 # pump out diffs from before the synch point
2025-07-02 04:52:33.695 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.695
2025-07-02 04:52:33.695 # do intraline marking on the synch pair
2025-07-02 04:52:33.695 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.695 if eqi is None:
2025-07-02 04:52:33.695 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.695 atags = btags = ""
2025-07-02 04:52:33.695 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.695 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.695 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.695 if tag == 'replace':
2025-07-02 04:52:33.695 atags += '^' * la
2025-07-02 04:52:33.695 btags += '^' * lb
2025-07-02 04:52:33.695 elif tag == 'delete':
2025-07-02 04:52:33.695 atags += '-' * la
2025-07-02 04:52:33.695 elif tag == 'insert':
2025-07-02 04:52:33.695 btags += '+' * lb
2025-07-02 04:52:33.695 elif tag == 'equal':
2025-07-02 04:52:33.696 atags += ' ' * la
2025-07-02 04:52:33.696 btags += ' ' * lb
2025-07-02 04:52:33.696 else:
2025-07-02 04:52:33.696 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.696 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.696 else:
2025-07-02 04:52:33.696 # the synch pair is identical
2025-07-02 04:52:33.696 yield ' ' + aelt
2025-07-02 04:52:33.696
2025-07-02 04:52:33.696 # pump out diffs from after the synch point
2025-07-02 04:52:33.696 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.696
2025-07-02 04:52:33.696 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.696 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.696
2025-07-02 04:52:33.696 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.696 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.696 alo = 454, ahi = 1101
2025-07-02 04:52:33.696 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.696 blo = 454, bhi = 1101
2025-07-02 04:52:33.697
2025-07-02 04:52:33.697 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.697 g = []
2025-07-02 04:52:33.697 if alo < ahi:
2025-07-02 04:52:33.697 if blo < bhi:
2025-07-02 04:52:33.697 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.697 else:
2025-07-02 04:52:33.697 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.697 elif blo < bhi:
2025-07-02 04:52:33.697 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.697
2025-07-02 04:52:33.697 > yield from g
2025-07-02 04:52:33.697
2025-07-02 04:52:33.697 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.697 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.697
2025-07-02 04:52:33.697 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.697 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.697 alo = 454, ahi = 1101
2025-07-02 04:52:33.697 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.697 blo = 454, bhi = 1101
2025-07-02 04:52:33.698
2025-07-02 04:52:33.698 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.698 r"""
2025-07-02 04:52:33.698 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.698 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.698 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.698 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.698
2025-07-02 04:52:33.698 Example:
2025-07-02 04:52:33.698
2025-07-02 04:52:33.698 >>> d = Differ()
2025-07-02 04:52:33.698 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.698 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.698 >>> print(''.join(results), end="")
2025-07-02 04:52:33.698 - abcDefghiJkl
2025-07-02 04:52:33.698 + abcdefGhijkl
2025-07-02 04:52:33.698 """
2025-07-02 04:52:33.699
2025-07-02 04:52:33.699 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.699 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.699 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.699 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.699 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.699
2025-07-02 04:52:33.699 # search for the pair that matches best without being identical
2025-07-02 04:52:33.699 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.699 # on junk -- unless we have to)
2025-07-02 04:52:33.699 for j in range(blo, bhi):
2025-07-02 04:52:33.699 bj = b[j]
2025-07-02 04:52:33.699 cruncher.set_seq2(bj)
2025-07-02 04:52:33.699 for i in range(alo, ahi):
2025-07-02 04:52:33.699 ai = a[i]
2025-07-02 04:52:33.699 if ai == bj:
2025-07-02 04:52:33.699 if eqi is None:
2025-07-02 04:52:33.699 eqi, eqj = i, j
2025-07-02 04:52:33.699 continue
2025-07-02 04:52:33.699 cruncher.set_seq1(ai)
2025-07-02 04:52:33.699 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.700 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.700 # compares by a factor of 3.
2025-07-02 04:52:33.700 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.700 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.700 # of the computation is cached by cruncher
2025-07-02 04:52:33.700 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.700 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.700 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.700 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.700 if best_ratio < cutoff:
2025-07-02 04:52:33.700 # no non-identical "pretty close" pair
2025-07-02 04:52:33.700 if eqi is None:
2025-07-02 04:52:33.700 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.700 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.700 return
2025-07-02 04:52:33.700 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.700 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.700 else:
2025-07-02 04:52:33.700 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.700 eqi = None
2025-07-02 04:52:33.700
2025-07-02 04:52:33.700 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.701 # identical
2025-07-02 04:52:33.701
2025-07-02 04:52:33.701 # pump out diffs from before the synch point
2025-07-02 04:52:33.701 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.701
2025-07-02 04:52:33.701 # do intraline marking on the synch pair
2025-07-02 04:52:33.701 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.701 if eqi is None:
2025-07-02 04:52:33.701 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.701 atags = btags = ""
2025-07-02 04:52:33.701 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.701 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.701 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.701 if tag == 'replace':
2025-07-02 04:52:33.701 atags += '^' * la
2025-07-02 04:52:33.701 btags += '^' * lb
2025-07-02 04:52:33.701 elif tag == 'delete':
2025-07-02 04:52:33.701 atags += '-' * la
2025-07-02 04:52:33.701 elif tag == 'insert':
2025-07-02 04:52:33.701 btags += '+' * lb
2025-07-02 04:52:33.701 elif tag == 'equal':
2025-07-02 04:52:33.702 atags += ' ' * la
2025-07-02 04:52:33.702 btags += ' ' * lb
2025-07-02 04:52:33.702 else:
2025-07-02 04:52:33.702 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.702 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.702 else:
2025-07-02 04:52:33.702 # the synch pair is identical
2025-07-02 04:52:33.702 yield ' ' + aelt
2025-07-02 04:52:33.702
2025-07-02 04:52:33.702 # pump out diffs from after the synch point
2025-07-02 04:52:33.702 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.702
2025-07-02 04:52:33.702 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.702 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.702
2025-07-02 04:52:33.702 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.702 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.702 alo = 455, ahi = 1101
2025-07-02 04:52:33.702 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.702 blo = 455, bhi = 1101
2025-07-02 04:52:33.702
2025-07-02 04:52:33.702 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.703 g = []
2025-07-02 04:52:33.703 if alo < ahi:
2025-07-02 04:52:33.703 if blo < bhi:
2025-07-02 04:52:33.703 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.703 else:
2025-07-02 04:52:33.703 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.703 elif blo < bhi:
2025-07-02 04:52:33.703 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.703
2025-07-02 04:52:33.703 > yield from g
2025-07-02 04:52:33.703
2025-07-02 04:52:33.703 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.703 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.703
2025-07-02 04:52:33.703 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.703 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.703 alo = 455, ahi = 1101
2025-07-02 04:52:33.703 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.703 blo = 455, bhi = 1101
2025-07-02 04:52:33.703
2025-07-02 04:52:33.704 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.704 r"""
2025-07-02 04:52:33.704 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.704 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.704 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.704 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.704
2025-07-02 04:52:33.704 Example:
2025-07-02 04:52:33.704
2025-07-02 04:52:33.704 >>> d = Differ()
2025-07-02 04:52:33.704 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.704 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.704 >>> print(''.join(results), end="")
2025-07-02 04:52:33.704 - abcDefghiJkl
2025-07-02 04:52:33.704 + abcdefGhijkl
2025-07-02 04:52:33.704 """
2025-07-02 04:52:33.704
2025-07-02 04:52:33.704 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.705 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.705 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.705 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.705 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.705
2025-07-02 04:52:33.705 # search for the pair that matches best without being identical
2025-07-02 04:52:33.705 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.705 # on junk -- unless we have to)
2025-07-02 04:52:33.705 for j in range(blo, bhi):
2025-07-02 04:52:33.705 bj = b[j]
2025-07-02 04:52:33.705 cruncher.set_seq2(bj)
2025-07-02 04:52:33.705 for i in range(alo, ahi):
2025-07-02 04:52:33.705 ai = a[i]
2025-07-02 04:52:33.705 if ai == bj:
2025-07-02 04:52:33.705 if eqi is None:
2025-07-02 04:52:33.705 eqi, eqj = i, j
2025-07-02 04:52:33.705 continue
2025-07-02 04:52:33.705 cruncher.set_seq1(ai)
2025-07-02 04:52:33.705 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.705 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.706 # compares by a factor of 3.
2025-07-02 04:52:33.706 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.706 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.706 # of the computation is cached by cruncher
2025-07-02 04:52:33.706 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.706 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.706 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.706 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.706 if best_ratio < cutoff:
2025-07-02 04:52:33.706 # no non-identical "pretty close" pair
2025-07-02 04:52:33.706 if eqi is None:
2025-07-02 04:52:33.706 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.706 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.706 return
2025-07-02 04:52:33.706 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.706 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.706 else:
2025-07-02 04:52:33.706 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.706 eqi = None
2025-07-02 04:52:33.706
2025-07-02 04:52:33.706 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.707 # identical
2025-07-02 04:52:33.707
2025-07-02 04:52:33.707 # pump out diffs from before the synch point
2025-07-02 04:52:33.707 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.707
2025-07-02 04:52:33.707 # do intraline marking on the synch pair
2025-07-02 04:52:33.707 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.707 if eqi is None:
2025-07-02 04:52:33.707 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.707 atags = btags = ""
2025-07-02 04:52:33.707 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.707 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.707 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.707 if tag == 'replace':
2025-07-02 04:52:33.707 atags += '^' * la
2025-07-02 04:52:33.707 btags += '^' * lb
2025-07-02 04:52:33.707 elif tag == 'delete':
2025-07-02 04:52:33.707 atags += '-' * la
2025-07-02 04:52:33.707 elif tag == 'insert':
2025-07-02 04:52:33.707 btags += '+' * lb
2025-07-02 04:52:33.707 elif tag == 'equal':
2025-07-02 04:52:33.707 atags += ' ' * la
2025-07-02 04:52:33.708 btags += ' ' * lb
2025-07-02 04:52:33.708 else:
2025-07-02 04:52:33.708 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.708 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.708 else:
2025-07-02 04:52:33.708 # the synch pair is identical
2025-07-02 04:52:33.708 yield ' ' + aelt
2025-07-02 04:52:33.708
2025-07-02 04:52:33.708 # pump out diffs from after the synch point
2025-07-02 04:52:33.708 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.708
2025-07-02 04:52:33.708 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.708 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.708
2025-07-02 04:52:33.708 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.708 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.708 alo = 456, ahi = 1101
2025-07-02 04:52:33.708 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.708 blo = 456, bhi = 1101
2025-07-02 04:52:33.708
2025-07-02 04:52:33.708 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.709 g = []
2025-07-02 04:52:33.709 if alo < ahi:
2025-07-02 04:52:33.709 if blo < bhi:
2025-07-02 04:52:33.709 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.709 else:
2025-07-02 04:52:33.709 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.709 elif blo < bhi:
2025-07-02 04:52:33.709 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.709
2025-07-02 04:52:33.709 > yield from g
2025-07-02 04:52:33.709
2025-07-02 04:52:33.709 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.709 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.709
2025-07-02 04:52:33.709 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.709 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.709 alo = 456, ahi = 1101
2025-07-02 04:52:33.709 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.709 blo = 456, bhi = 1101
2025-07-02 04:52:33.709
2025-07-02 04:52:33.709 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.710 r"""
2025-07-02 04:52:33.710 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.710 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.710 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.710 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.710
2025-07-02 04:52:33.710 Example:
2025-07-02 04:52:33.710
2025-07-02 04:52:33.710 >>> d = Differ()
2025-07-02 04:52:33.710 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.710 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.710 >>> print(''.join(results), end="")
2025-07-02 04:52:33.710 - abcDefghiJkl
2025-07-02 04:52:33.710 + abcdefGhijkl
2025-07-02 04:52:33.710 """
2025-07-02 04:52:33.710
2025-07-02 04:52:33.710 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.710 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.710 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.710 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.711 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.711
2025-07-02 04:52:33.711 # search for the pair that matches best without being identical
2025-07-02 04:52:33.711 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.711 # on junk -- unless we have to)
2025-07-02 04:52:33.711 for j in range(blo, bhi):
2025-07-02 04:52:33.711 bj = b[j]
2025-07-02 04:52:33.711 cruncher.set_seq2(bj)
2025-07-02 04:52:33.711 for i in range(alo, ahi):
2025-07-02 04:52:33.711 ai = a[i]
2025-07-02 04:52:33.711 if ai == bj:
2025-07-02 04:52:33.711 if eqi is None:
2025-07-02 04:52:33.711 eqi, eqj = i, j
2025-07-02 04:52:33.711 continue
2025-07-02 04:52:33.711 cruncher.set_seq1(ai)
2025-07-02 04:52:33.711 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.711 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.711 # compares by a factor of 3.
2025-07-02 04:52:33.711 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.711 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.711 # of the computation is cached by cruncher
2025-07-02 04:52:33.711 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.712 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.712 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.712 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.712 if best_ratio < cutoff:
2025-07-02 04:52:33.712 # no non-identical "pretty close" pair
2025-07-02 04:52:33.712 if eqi is None:
2025-07-02 04:52:33.712 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.712 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.712 return
2025-07-02 04:52:33.712 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.712 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.712 else:
2025-07-02 04:52:33.712 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.712 eqi = None
2025-07-02 04:52:33.712
2025-07-02 04:52:33.712 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.712 # identical
2025-07-02 04:52:33.712
2025-07-02 04:52:33.712 # pump out diffs from before the synch point
2025-07-02 04:52:33.713 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.713
2025-07-02 04:52:33.713 # do intraline marking on the synch pair
2025-07-02 04:52:33.713 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.713 if eqi is None:
2025-07-02 04:52:33.713 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.713 atags = btags = ""
2025-07-02 04:52:33.713 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.713 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.713 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.713 if tag == 'replace':
2025-07-02 04:52:33.713 atags += '^' * la
2025-07-02 04:52:33.713 btags += '^' * lb
2025-07-02 04:52:33.713 elif tag == 'delete':
2025-07-02 04:52:33.713 atags += '-' * la
2025-07-02 04:52:33.713 elif tag == 'insert':
2025-07-02 04:52:33.713 btags += '+' * lb
2025-07-02 04:52:33.713 elif tag == 'equal':
2025-07-02 04:52:33.713 atags += ' ' * la
2025-07-02 04:52:33.713 btags += ' ' * lb
2025-07-02 04:52:33.714 else:
2025-07-02 04:52:33.714 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.714 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.714 else:
2025-07-02 04:52:33.714 # the synch pair is identical
2025-07-02 04:52:33.714 yield ' ' + aelt
2025-07-02 04:52:33.714
2025-07-02 04:52:33.714 # pump out diffs from after the synch point
2025-07-02 04:52:33.714 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.714
2025-07-02 04:52:33.714 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.714 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.714
2025-07-02 04:52:33.714 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.714 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.714 alo = 457, ahi = 1101
2025-07-02 04:52:33.714 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.715 blo = 457, bhi = 1101
2025-07-02 04:52:33.715
2025-07-02 04:52:33.715 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.715 g = []
2025-07-02 04:52:33.715 if alo < ahi:
2025-07-02 04:52:33.715 if blo < bhi:
2025-07-02 04:52:33.715 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.715 else:
2025-07-02 04:52:33.715 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.715 elif blo < bhi:
2025-07-02 04:52:33.715 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.715
2025-07-02 04:52:33.715 > yield from g
2025-07-02 04:52:33.715
2025-07-02 04:52:33.715 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.715 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.715
2025-07-02 04:52:33.715 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.715 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.715 alo = 457, ahi = 1101
2025-07-02 04:52:33.715 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.716 blo = 457, bhi = 1101
2025-07-02 04:52:33.716
2025-07-02 04:52:33.716 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.716 r"""
2025-07-02 04:52:33.716 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.716 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.716 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.716 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.716
2025-07-02 04:52:33.716 Example:
2025-07-02 04:52:33.716
2025-07-02 04:52:33.716 >>> d = Differ()
2025-07-02 04:52:33.716 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.716 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.716 >>> print(''.join(results), end="")
2025-07-02 04:52:33.716 - abcDefghiJkl
2025-07-02 04:52:33.716 + abcdefGhijkl
2025-07-02 04:52:33.716 """
2025-07-02 04:52:33.717
2025-07-02 04:52:33.717 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.717 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.717 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.717 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.717 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.717
2025-07-02 04:52:33.717 # search for the pair that matches best without being identical
2025-07-02 04:52:33.717 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.717 # on junk -- unless we have to)
2025-07-02 04:52:33.717 for j in range(blo, bhi):
2025-07-02 04:52:33.717 bj = b[j]
2025-07-02 04:52:33.717 cruncher.set_seq2(bj)
2025-07-02 04:52:33.717 for i in range(alo, ahi):
2025-07-02 04:52:33.717 ai = a[i]
2025-07-02 04:52:33.717 if ai == bj:
2025-07-02 04:52:33.717 if eqi is None:
2025-07-02 04:52:33.717 eqi, eqj = i, j
2025-07-02 04:52:33.717 continue
2025-07-02 04:52:33.717 cruncher.set_seq1(ai)
2025-07-02 04:52:33.717 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.718 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.718 # compares by a factor of 3.
2025-07-02 04:52:33.718 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.718 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.718 # of the computation is cached by cruncher
2025-07-02 04:52:33.718 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.718 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.718 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.718 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.718 if best_ratio < cutoff:
2025-07-02 04:52:33.718 # no non-identical "pretty close" pair
2025-07-02 04:52:33.718 if eqi is None:
2025-07-02 04:52:33.718 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.718 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.718 return
2025-07-02 04:52:33.718 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.718 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.718 else:
2025-07-02 04:52:33.718 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.718 eqi = None
2025-07-02 04:52:33.719
2025-07-02 04:52:33.719 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.719 # identical
2025-07-02 04:52:33.719
2025-07-02 04:52:33.719 # pump out diffs from before the synch point
2025-07-02 04:52:33.719 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.719
2025-07-02 04:52:33.719 # do intraline marking on the synch pair
2025-07-02 04:52:33.719 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.719 if eqi is None:
2025-07-02 04:52:33.719 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.719 atags = btags = ""
2025-07-02 04:52:33.719 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.719 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.719 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.719 if tag == 'replace':
2025-07-02 04:52:33.719 atags += '^' * la
2025-07-02 04:52:33.719 btags += '^' * lb
2025-07-02 04:52:33.719 elif tag == 'delete':
2025-07-02 04:52:33.719 atags += '-' * la
2025-07-02 04:52:33.719 elif tag == 'insert':
2025-07-02 04:52:33.720 btags += '+' * lb
2025-07-02 04:52:33.720 elif tag == 'equal':
2025-07-02 04:52:33.720 atags += ' ' * la
2025-07-02 04:52:33.720 btags += ' ' * lb
2025-07-02 04:52:33.720 else:
2025-07-02 04:52:33.720 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.720 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.720 else:
2025-07-02 04:52:33.720 # the synch pair is identical
2025-07-02 04:52:33.720 yield ' ' + aelt
2025-07-02 04:52:33.720
2025-07-02 04:52:33.720 # pump out diffs from after the synch point
2025-07-02 04:52:33.720 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.720
2025-07-02 04:52:33.720 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.720 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.720
2025-07-02 04:52:33.720 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.720 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.720 alo = 458, ahi = 1101
2025-07-02 04:52:33.721 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.721 blo = 458, bhi = 1101
2025-07-02 04:52:33.721
2025-07-02 04:52:33.721 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.721 g = []
2025-07-02 04:52:33.721 if alo < ahi:
2025-07-02 04:52:33.721 if blo < bhi:
2025-07-02 04:52:33.721 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.721 else:
2025-07-02 04:52:33.721 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.721 elif blo < bhi:
2025-07-02 04:52:33.721 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.721
2025-07-02 04:52:33.721 > yield from g
2025-07-02 04:52:33.721
2025-07-02 04:52:33.721 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.721 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.721
2025-07-02 04:52:33.721 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.722 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.722 alo = 458, ahi = 1101
2025-07-02 04:52:33.722 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.722 blo = 458, bhi = 1101
2025-07-02 04:52:33.722
2025-07-02 04:52:33.722 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.722 r"""
2025-07-02 04:52:33.722 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.722 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.722 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.722 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.722
2025-07-02 04:52:33.722 Example:
2025-07-02 04:52:33.722
2025-07-02 04:52:33.722 >>> d = Differ()
2025-07-02 04:52:33.722 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.722 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.722 >>> print(''.join(results), end="")
2025-07-02 04:52:33.722 - abcDefghiJkl
2025-07-02 04:52:33.723 + abcdefGhijkl
2025-07-02 04:52:33.723 """
2025-07-02 04:52:33.723
2025-07-02 04:52:33.723 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.723 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.723 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.723 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.723 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.723
2025-07-02 04:52:33.723 # search for the pair that matches best without being identical
2025-07-02 04:52:33.723 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.723 # on junk -- unless we have to)
2025-07-02 04:52:33.723 for j in range(blo, bhi):
2025-07-02 04:52:33.723 bj = b[j]
2025-07-02 04:52:33.723 cruncher.set_seq2(bj)
2025-07-02 04:52:33.723 for i in range(alo, ahi):
2025-07-02 04:52:33.723 ai = a[i]
2025-07-02 04:52:33.723 if ai == bj:
2025-07-02 04:52:33.723 if eqi is None:
2025-07-02 04:52:33.723 eqi, eqj = i, j
2025-07-02 04:52:33.724 continue
2025-07-02 04:52:33.724 cruncher.set_seq1(ai)
2025-07-02 04:52:33.724 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.724 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.724 # compares by a factor of 3.
2025-07-02 04:52:33.724 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.724 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.724 # of the computation is cached by cruncher
2025-07-02 04:52:33.724 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.724 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.724 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.724 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.724 if best_ratio < cutoff:
2025-07-02 04:52:33.724 # no non-identical "pretty close" pair
2025-07-02 04:52:33.724 if eqi is None:
2025-07-02 04:52:33.724 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.724 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.724 return
2025-07-02 04:52:33.724 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.724 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.724 else:
2025-07-02 04:52:33.725 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.725 eqi = None
2025-07-02 04:52:33.725
2025-07-02 04:52:33.725 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.725 # identical
2025-07-02 04:52:33.725
2025-07-02 04:52:33.725 # pump out diffs from before the synch point
2025-07-02 04:52:33.725 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.725
2025-07-02 04:52:33.725 # do intraline marking on the synch pair
2025-07-02 04:52:33.725 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.725 if eqi is None:
2025-07-02 04:52:33.725 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.725 atags = btags = ""
2025-07-02 04:52:33.725 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.725 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.725 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.725 if tag == 'replace':
2025-07-02 04:52:33.725 atags += '^' * la
2025-07-02 04:52:33.725 btags += '^' * lb
2025-07-02 04:52:33.725 elif tag == 'delete':
2025-07-02 04:52:33.726 atags += '-' * la
2025-07-02 04:52:33.726 elif tag == 'insert':
2025-07-02 04:52:33.726 btags += '+' * lb
2025-07-02 04:52:33.726 elif tag == 'equal':
2025-07-02 04:52:33.726 atags += ' ' * la
2025-07-02 04:52:33.726 btags += ' ' * lb
2025-07-02 04:52:33.726 else:
2025-07-02 04:52:33.726 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.726 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.726 else:
2025-07-02 04:52:33.726 # the synch pair is identical
2025-07-02 04:52:33.726 yield ' ' + aelt
2025-07-02 04:52:33.726
2025-07-02 04:52:33.726 # pump out diffs from after the synch point
2025-07-02 04:52:33.726 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.726
2025-07-02 04:52:33.726 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.726 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.726
2025-07-02 04:52:33.726 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.726 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.726 alo = 459, ahi = 1101
2025-07-02 04:52:33.727 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.727 blo = 459, bhi = 1101
2025-07-02 04:52:33.727
2025-07-02 04:52:33.727 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.727 g = []
2025-07-02 04:52:33.727 if alo < ahi:
2025-07-02 04:52:33.727 if blo < bhi:
2025-07-02 04:52:33.727 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.727 else:
2025-07-02 04:52:33.727 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.727 elif blo < bhi:
2025-07-02 04:52:33.727 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.727
2025-07-02 04:52:33.727 > yield from g
2025-07-02 04:52:33.727
2025-07-02 04:52:33.727 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.727 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.727
2025-07-02 04:52:33.727 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.727 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.727 alo = 459, ahi = 1101
2025-07-02 04:52:33.728 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.728 blo = 459, bhi = 1101
2025-07-02 04:52:33.728
2025-07-02 04:52:33.728 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.728 r"""
2025-07-02 04:52:33.728 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.728 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.728 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.728 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.728
2025-07-02 04:52:33.728 Example:
2025-07-02 04:52:33.728
2025-07-02 04:52:33.728 >>> d = Differ()
2025-07-02 04:52:33.728 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.728 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.728 >>> print(''.join(results), end="")
2025-07-02 04:52:33.728 - abcDefghiJkl
2025-07-02 04:52:33.728 + abcdefGhijkl
2025-07-02 04:52:33.728 """
2025-07-02 04:52:33.729
2025-07-02 04:52:33.729 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.729 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.729 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.729 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.729 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.729
2025-07-02 04:52:33.729 # search for the pair that matches best without being identical
2025-07-02 04:52:33.729 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.729 # on junk -- unless we have to)
2025-07-02 04:52:33.729 for j in range(blo, bhi):
2025-07-02 04:52:33.729 bj = b[j]
2025-07-02 04:52:33.729 cruncher.set_seq2(bj)
2025-07-02 04:52:33.729 for i in range(alo, ahi):
2025-07-02 04:52:33.729 ai = a[i]
2025-07-02 04:52:33.729 if ai == bj:
2025-07-02 04:52:33.729 if eqi is None:
2025-07-02 04:52:33.729 eqi, eqj = i, j
2025-07-02 04:52:33.729 continue
2025-07-02 04:52:33.730 cruncher.set_seq1(ai)
2025-07-02 04:52:33.730 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.730 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.730 # compares by a factor of 3.
2025-07-02 04:52:33.730 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.730 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.730 # of the computation is cached by cruncher
2025-07-02 04:52:33.730 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.730 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.730 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.730 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.730 if best_ratio < cutoff:
2025-07-02 04:52:33.730 # no non-identical "pretty close" pair
2025-07-02 04:52:33.730 if eqi is None:
2025-07-02 04:52:33.730 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.730 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.730 return
2025-07-02 04:52:33.730 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.730 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.731 else:
2025-07-02 04:52:33.731 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.731 eqi = None
2025-07-02 04:52:33.731
2025-07-02 04:52:33.731 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.731 # identical
2025-07-02 04:52:33.731
2025-07-02 04:52:33.731 # pump out diffs from before the synch point
2025-07-02 04:52:33.731 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.731
2025-07-02 04:52:33.731 # do intraline marking on the synch pair
2025-07-02 04:52:33.731 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.731 if eqi is None:
2025-07-02 04:52:33.731 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.731 atags = btags = ""
2025-07-02 04:52:33.731 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.731 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.731 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.731 if tag == 'replace':
2025-07-02 04:52:33.731 atags += '^' * la
2025-07-02 04:52:33.731 btags += '^' * lb
2025-07-02 04:52:33.732 elif tag == 'delete':
2025-07-02 04:52:33.732 atags += '-' * la
2025-07-02 04:52:33.732 elif tag == 'insert':
2025-07-02 04:52:33.732 btags += '+' * lb
2025-07-02 04:52:33.732 elif tag == 'equal':
2025-07-02 04:52:33.732 atags += ' ' * la
2025-07-02 04:52:33.732 btags += ' ' * lb
2025-07-02 04:52:33.732 else:
2025-07-02 04:52:33.732 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.732 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.732 else:
2025-07-02 04:52:33.732 # the synch pair is identical
2025-07-02 04:52:33.732 yield ' ' + aelt
2025-07-02 04:52:33.732
2025-07-02 04:52:33.732 # pump out diffs from after the synch point
2025-07-02 04:52:33.732 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.732
2025-07-02 04:52:33.732 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.732 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.732
2025-07-02 04:52:33.733 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.733 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.733 alo = 460, ahi = 1101
2025-07-02 04:52:33.733 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.733 blo = 460, bhi = 1101
2025-07-02 04:52:33.733
2025-07-02 04:52:33.733 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.733 g = []
2025-07-02 04:52:33.733 if alo < ahi:
2025-07-02 04:52:33.733 if blo < bhi:
2025-07-02 04:52:33.733 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.733 else:
2025-07-02 04:52:33.733 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.733 elif blo < bhi:
2025-07-02 04:52:33.733 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.733
2025-07-02 04:52:33.733 > yield from g
2025-07-02 04:52:33.733
2025-07-02 04:52:33.733 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.733 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.733
2025-07-02 04:52:33.733 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.734 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.734 alo = 460, ahi = 1101
2025-07-02 04:52:33.734 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.734 blo = 460, bhi = 1101
2025-07-02 04:52:33.734
2025-07-02 04:52:33.734 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.734 r"""
2025-07-02 04:52:33.734 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.734 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.734 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.734 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.734
2025-07-02 04:52:33.734 Example:
2025-07-02 04:52:33.734
2025-07-02 04:52:33.734 >>> d = Differ()
2025-07-02 04:52:33.734 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.734 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.734 >>> print(''.join(results), end="")
2025-07-02 04:52:33.734 - abcDefghiJkl
2025-07-02 04:52:33.734 + abcdefGhijkl
2025-07-02 04:52:33.735 """
2025-07-02 04:52:33.735
2025-07-02 04:52:33.735 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.735 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.735 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.735 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.735 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.735
2025-07-02 04:52:33.735 # search for the pair that matches best without being identical
2025-07-02 04:52:33.735 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.735 # on junk -- unless we have to)
2025-07-02 04:52:33.735 for j in range(blo, bhi):
2025-07-02 04:52:33.735 bj = b[j]
2025-07-02 04:52:33.735 cruncher.set_seq2(bj)
2025-07-02 04:52:33.735 for i in range(alo, ahi):
2025-07-02 04:52:33.735 ai = a[i]
2025-07-02 04:52:33.735 if ai == bj:
2025-07-02 04:52:33.735 if eqi is None:
2025-07-02 04:52:33.735 eqi, eqj = i, j
2025-07-02 04:52:33.735 continue
2025-07-02 04:52:33.736 cruncher.set_seq1(ai)
2025-07-02 04:52:33.736 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.736 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.736 # compares by a factor of 3.
2025-07-02 04:52:33.736 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.736 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.736 # of the computation is cached by cruncher
2025-07-02 04:52:33.736 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.736 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.736 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.736 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.736 if best_ratio < cutoff:
2025-07-02 04:52:33.736 # no non-identical "pretty close" pair
2025-07-02 04:52:33.736 if eqi is None:
2025-07-02 04:52:33.736 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.736 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.736 return
2025-07-02 04:52:33.736 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.736 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.736 else:
2025-07-02 04:52:33.736 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.737 eqi = None
2025-07-02 04:52:33.737
2025-07-02 04:52:33.737 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.737 # identical
2025-07-02 04:52:33.737
2025-07-02 04:52:33.737 # pump out diffs from before the synch point
2025-07-02 04:52:33.737 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.737
2025-07-02 04:52:33.737 # do intraline marking on the synch pair
2025-07-02 04:52:33.737 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.737 if eqi is None:
2025-07-02 04:52:33.737 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.737 atags = btags = ""
2025-07-02 04:52:33.737 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.737 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.737 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.737 if tag == 'replace':
2025-07-02 04:52:33.737 atags += '^' * la
2025-07-02 04:52:33.737 btags += '^' * lb
2025-07-02 04:52:33.738 elif tag == 'delete':
2025-07-02 04:52:33.738 atags += '-' * la
2025-07-02 04:52:33.738 elif tag == 'insert':
2025-07-02 04:52:33.738 btags += '+' * lb
2025-07-02 04:52:33.738 elif tag == 'equal':
2025-07-02 04:52:33.738 atags += ' ' * la
2025-07-02 04:52:33.738 btags += ' ' * lb
2025-07-02 04:52:33.738 else:
2025-07-02 04:52:33.738 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.738 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.738 else:
2025-07-02 04:52:33.738 # the synch pair is identical
2025-07-02 04:52:33.738 yield ' ' + aelt
2025-07-02 04:52:33.738
2025-07-02 04:52:33.738 # pump out diffs from after the synch point
2025-07-02 04:52:33.738 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.738
2025-07-02 04:52:33.738 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.739 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.739
2025-07-02 04:52:33.739 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.739 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.739 alo = 461, ahi = 1101
2025-07-02 04:52:33.739 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.739 blo = 461, bhi = 1101
2025-07-02 04:52:33.739
2025-07-02 04:52:33.739 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.739 g = []
2025-07-02 04:52:33.739 if alo < ahi:
2025-07-02 04:52:33.739 if blo < bhi:
2025-07-02 04:52:33.739 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.739 else:
2025-07-02 04:52:33.739 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.739 elif blo < bhi:
2025-07-02 04:52:33.739 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.739
2025-07-02 04:52:33.739 > yield from g
2025-07-02 04:52:33.739
2025-07-02 04:52:33.739 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.740 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.740
2025-07-02 04:52:33.740 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.740 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.740 alo = 461, ahi = 1101
2025-07-02 04:52:33.740 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.740 blo = 461, bhi = 1101
2025-07-02 04:52:33.740
2025-07-02 04:52:33.740 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.740 r"""
2025-07-02 04:52:33.740 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.740 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.740 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.740 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.740
2025-07-02 04:52:33.740 Example:
2025-07-02 04:52:33.740
2025-07-02 04:52:33.740 >>> d = Differ()
2025-07-02 04:52:33.740 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.740 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.741 >>> print(''.join(results), end="")
2025-07-02 04:52:33.741 - abcDefghiJkl
2025-07-02 04:52:33.741 + abcdefGhijkl
2025-07-02 04:52:33.741 """
2025-07-02 04:52:33.741
2025-07-02 04:52:33.741 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.741 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.741 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.741 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.741 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.741
2025-07-02 04:52:33.741 # search for the pair that matches best without being identical
2025-07-02 04:52:33.741 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.741 # on junk -- unless we have to)
2025-07-02 04:52:33.741 for j in range(blo, bhi):
2025-07-02 04:52:33.741 bj = b[j]
2025-07-02 04:52:33.741 cruncher.set_seq2(bj)
2025-07-02 04:52:33.741 for i in range(alo, ahi):
2025-07-02 04:52:33.741 ai = a[i]
2025-07-02 04:52:33.741 if ai == bj:
2025-07-02 04:52:33.742 if eqi is None:
2025-07-02 04:52:33.742 eqi, eqj = i, j
2025-07-02 04:52:33.742 continue
2025-07-02 04:52:33.742 cruncher.set_seq1(ai)
2025-07-02 04:52:33.742 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.742 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.742 # compares by a factor of 3.
2025-07-02 04:52:33.742 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.742 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.742 # of the computation is cached by cruncher
2025-07-02 04:52:33.742 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.742 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.742 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.742 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.742 if best_ratio < cutoff:
2025-07-02 04:52:33.742 # no non-identical "pretty close" pair
2025-07-02 04:52:33.742 if eqi is None:
2025-07-02 04:52:33.742 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.742 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.742 return
2025-07-02 04:52:33.743 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.743 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.743 else:
2025-07-02 04:52:33.743 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.743 eqi = None
2025-07-02 04:52:33.743
2025-07-02 04:52:33.743 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.743 # identical
2025-07-02 04:52:33.743
2025-07-02 04:52:33.743 # pump out diffs from before the synch point
2025-07-02 04:52:33.743 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.743
2025-07-02 04:52:33.743 # do intraline marking on the synch pair
2025-07-02 04:52:33.743 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.743 if eqi is None:
2025-07-02 04:52:33.743 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.743 atags = btags = ""
2025-07-02 04:52:33.743 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.743 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.744 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.744 if tag == 'replace':
2025-07-02 04:52:33.744 atags += '^' * la
2025-07-02 04:52:33.744 btags += '^' * lb
2025-07-02 04:52:33.744 elif tag == 'delete':
2025-07-02 04:52:33.744 atags += '-' * la
2025-07-02 04:52:33.744 elif tag == 'insert':
2025-07-02 04:52:33.744 btags += '+' * lb
2025-07-02 04:52:33.744 elif tag == 'equal':
2025-07-02 04:52:33.744 atags += ' ' * la
2025-07-02 04:52:33.744 btags += ' ' * lb
2025-07-02 04:52:33.744 else:
2025-07-02 04:52:33.744 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.744 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.744 else:
2025-07-02 04:52:33.744 # the synch pair is identical
2025-07-02 04:52:33.744 yield ' ' + aelt
2025-07-02 04:52:33.744
2025-07-02 04:52:33.744 # pump out diffs from after the synch point
2025-07-02 04:52:33.744 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.744
2025-07-02 04:52:33.744 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.745 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.745
2025-07-02 04:52:33.745 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.745 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.745 alo = 462, ahi = 1101
2025-07-02 04:52:33.745 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.745 blo = 462, bhi = 1101
2025-07-02 04:52:33.745
2025-07-02 04:52:33.745 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.745 g = []
2025-07-02 04:52:33.745 if alo < ahi:
2025-07-02 04:52:33.745 if blo < bhi:
2025-07-02 04:52:33.745 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.745 else:
2025-07-02 04:52:33.745 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.745 elif blo < bhi:
2025-07-02 04:52:33.745 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.745
2025-07-02 04:52:33.745 > yield from g
2025-07-02 04:52:33.745
2025-07-02 04:52:33.745 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.746 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.746
2025-07-02 04:52:33.746 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.746 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.746 alo = 462, ahi = 1101
2025-07-02 04:52:33.746 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.746 blo = 462, bhi = 1101
2025-07-02 04:52:33.746
2025-07-02 04:52:33.746 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.746 r"""
2025-07-02 04:52:33.746 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.746 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.746 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.746 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.746
2025-07-02 04:52:33.746 Example:
2025-07-02 04:52:33.746
2025-07-02 04:52:33.747 >>> d = Differ()
2025-07-02 04:52:33.747 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.747 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.747 >>> print(''.join(results), end="")
2025-07-02 04:52:33.747 - abcDefghiJkl
2025-07-02 04:52:33.747 + abcdefGhijkl
2025-07-02 04:52:33.747 """
2025-07-02 04:52:33.747
2025-07-02 04:52:33.747 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.747 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.747 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.747 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.747 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.747
2025-07-02 04:52:33.747 # search for the pair that matches best without being identical
2025-07-02 04:52:33.747 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.747 # on junk -- unless we have to)
2025-07-02 04:52:33.747 for j in range(blo, bhi):
2025-07-02 04:52:33.747 bj = b[j]
2025-07-02 04:52:33.748 cruncher.set_seq2(bj)
2025-07-02 04:52:33.748 for i in range(alo, ahi):
2025-07-02 04:52:33.748 ai = a[i]
2025-07-02 04:52:33.748 if ai == bj:
2025-07-02 04:52:33.748 if eqi is None:
2025-07-02 04:52:33.748 eqi, eqj = i, j
2025-07-02 04:52:33.748 continue
2025-07-02 04:52:33.748 cruncher.set_seq1(ai)
2025-07-02 04:52:33.748 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.748 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.748 # compares by a factor of 3.
2025-07-02 04:52:33.748 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.748 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.748 # of the computation is cached by cruncher
2025-07-02 04:52:33.748 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.748 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.748 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.748 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.748 if best_ratio < cutoff:
2025-07-02 04:52:33.748 # no non-identical "pretty close" pair
2025-07-02 04:52:33.748 if eqi is None:
2025-07-02 04:52:33.749 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.749 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.749 return
2025-07-02 04:52:33.749 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.749 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.749 else:
2025-07-02 04:52:33.749 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.749 eqi = None
2025-07-02 04:52:33.749
2025-07-02 04:52:33.749 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.749 # identical
2025-07-02 04:52:33.749
2025-07-02 04:52:33.749 # pump out diffs from before the synch point
2025-07-02 04:52:33.749 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.749
2025-07-02 04:52:33.749 # do intraline marking on the synch pair
2025-07-02 04:52:33.749 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.749 if eqi is None:
2025-07-02 04:52:33.749 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.749 atags = btags = ""
2025-07-02 04:52:33.750 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.750 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.750 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.750 if tag == 'replace':
2025-07-02 04:52:33.750 atags += '^' * la
2025-07-02 04:52:33.750 btags += '^' * lb
2025-07-02 04:52:33.750 elif tag == 'delete':
2025-07-02 04:52:33.750 atags += '-' * la
2025-07-02 04:52:33.750 elif tag == 'insert':
2025-07-02 04:52:33.750 btags += '+' * lb
2025-07-02 04:52:33.750 elif tag == 'equal':
2025-07-02 04:52:33.750 atags += ' ' * la
2025-07-02 04:52:33.750 btags += ' ' * lb
2025-07-02 04:52:33.750 else:
2025-07-02 04:52:33.750 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.750 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.750 else:
2025-07-02 04:52:33.750 # the synch pair is identical
2025-07-02 04:52:33.750 yield ' ' + aelt
2025-07-02 04:52:33.750
2025-07-02 04:52:33.750 # pump out diffs from after the synch point
2025-07-02 04:52:33.750 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.751
2025-07-02 04:52:33.751 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.751 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.751
2025-07-02 04:52:33.751 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.751 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.751 alo = 463, ahi = 1101
2025-07-02 04:52:33.751 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.751 blo = 463, bhi = 1101
2025-07-02 04:52:33.751
2025-07-02 04:52:33.751 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.751 g = []
2025-07-02 04:52:33.751 if alo < ahi:
2025-07-02 04:52:33.751 if blo < bhi:
2025-07-02 04:52:33.751 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.751 else:
2025-07-02 04:52:33.751 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.751 elif blo < bhi:
2025-07-02 04:52:33.751 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.751
2025-07-02 04:52:33.751 > yield from g
2025-07-02 04:52:33.752
2025-07-02 04:52:33.752 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.752 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.752
2025-07-02 04:52:33.752 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.752 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.752 alo = 463, ahi = 1101
2025-07-02 04:52:33.752 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.752 blo = 463, bhi = 1101
2025-07-02 04:52:33.752
2025-07-02 04:52:33.752 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.752 r"""
2025-07-02 04:52:33.752 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.752 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.752 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.752 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.752
2025-07-02 04:52:33.752 Example:
2025-07-02 04:52:33.752
2025-07-02 04:52:33.752 >>> d = Differ()
2025-07-02 04:52:33.752 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.753 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.753 >>> print(''.join(results), end="")
2025-07-02 04:52:33.753 - abcDefghiJkl
2025-07-02 04:52:33.753 + abcdefGhijkl
2025-07-02 04:52:33.753 """
2025-07-02 04:52:33.753
2025-07-02 04:52:33.753 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.753 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.753 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.753 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.753 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.753
2025-07-02 04:52:33.753 # search for the pair that matches best without being identical
2025-07-02 04:52:33.753 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.753 # on junk -- unless we have to)
2025-07-02 04:52:33.753 for j in range(blo, bhi):
2025-07-02 04:52:33.753 bj = b[j]
2025-07-02 04:52:33.753 cruncher.set_seq2(bj)
2025-07-02 04:52:33.753 for i in range(alo, ahi):
2025-07-02 04:52:33.753 ai = a[i]
2025-07-02 04:52:33.754 if ai == bj:
2025-07-02 04:52:33.754 if eqi is None:
2025-07-02 04:52:33.754 eqi, eqj = i, j
2025-07-02 04:52:33.754 continue
2025-07-02 04:52:33.754 cruncher.set_seq1(ai)
2025-07-02 04:52:33.754 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.754 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.754 # compares by a factor of 3.
2025-07-02 04:52:33.754 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.754 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.754 # of the computation is cached by cruncher
2025-07-02 04:52:33.754 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.754 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.754 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.754 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.754 if best_ratio < cutoff:
2025-07-02 04:52:33.754 # no non-identical "pretty close" pair
2025-07-02 04:52:33.754 if eqi is None:
2025-07-02 04:52:33.754 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.754 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.755 return
2025-07-02 04:52:33.755 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.755 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.755 else:
2025-07-02 04:52:33.755 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.755 eqi = None
2025-07-02 04:52:33.755
2025-07-02 04:52:33.755 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.755 # identical
2025-07-02 04:52:33.755
2025-07-02 04:52:33.755 # pump out diffs from before the synch point
2025-07-02 04:52:33.755 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.755
2025-07-02 04:52:33.755 # do intraline marking on the synch pair
2025-07-02 04:52:33.755 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.755 if eqi is None:
2025-07-02 04:52:33.755 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.755 atags = btags = ""
2025-07-02 04:52:33.755 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.755 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.755 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.756 if tag == 'replace':
2025-07-02 04:52:33.756 atags += '^' * la
2025-07-02 04:52:33.756 btags += '^' * lb
2025-07-02 04:52:33.756 elif tag == 'delete':
2025-07-02 04:52:33.756 atags += '-' * la
2025-07-02 04:52:33.756 elif tag == 'insert':
2025-07-02 04:52:33.756 btags += '+' * lb
2025-07-02 04:52:33.756 elif tag == 'equal':
2025-07-02 04:52:33.756 atags += ' ' * la
2025-07-02 04:52:33.756 btags += ' ' * lb
2025-07-02 04:52:33.756 else:
2025-07-02 04:52:33.756 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.756 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.756 else:
2025-07-02 04:52:33.756 # the synch pair is identical
2025-07-02 04:52:33.756 yield ' ' + aelt
2025-07-02 04:52:33.756
2025-07-02 04:52:33.756 # pump out diffs from after the synch point
2025-07-02 04:52:33.756 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.756
2025-07-02 04:52:33.756 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.757 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.757
2025-07-02 04:52:33.757 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.757 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.757 alo = 466, ahi = 1101
2025-07-02 04:52:33.757 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.757 blo = 466, bhi = 1101
2025-07-02 04:52:33.757
2025-07-02 04:52:33.757 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.757 g = []
2025-07-02 04:52:33.757 if alo < ahi:
2025-07-02 04:52:33.757 if blo < bhi:
2025-07-02 04:52:33.757 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.757 else:
2025-07-02 04:52:33.757 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.757 elif blo < bhi:
2025-07-02 04:52:33.757 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.757
2025-07-02 04:52:33.757 > yield from g
2025-07-02 04:52:33.757
2025-07-02 04:52:33.757 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.758 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.758
2025-07-02 04:52:33.758 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.758 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.758 alo = 466, ahi = 1101
2025-07-02 04:52:33.758 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.758 blo = 466, bhi = 1101
2025-07-02 04:52:33.758
2025-07-02 04:52:33.758 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.758 r"""
2025-07-02 04:52:33.758 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.758 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.758 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.758 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.758
2025-07-02 04:52:33.758 Example:
2025-07-02 04:52:33.758
2025-07-02 04:52:33.758 >>> d = Differ()
2025-07-02 04:52:33.758 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.758 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.758 >>> print(''.join(results), end="")
2025-07-02 04:52:33.759 - abcDefghiJkl
2025-07-02 04:52:33.759 + abcdefGhijkl
2025-07-02 04:52:33.759 """
2025-07-02 04:52:33.759
2025-07-02 04:52:33.759 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.759 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.759 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.759 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.759 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.759
2025-07-02 04:52:33.759 # search for the pair that matches best without being identical
2025-07-02 04:52:33.759 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.759 # on junk -- unless we have to)
2025-07-02 04:52:33.759 for j in range(blo, bhi):
2025-07-02 04:52:33.759 bj = b[j]
2025-07-02 04:52:33.759 cruncher.set_seq2(bj)
2025-07-02 04:52:33.759 for i in range(alo, ahi):
2025-07-02 04:52:33.759 ai = a[i]
2025-07-02 04:52:33.759 if ai == bj:
2025-07-02 04:52:33.759 if eqi is None:
2025-07-02 04:52:33.760 eqi, eqj = i, j
2025-07-02 04:52:33.760 continue
2025-07-02 04:52:33.760 cruncher.set_seq1(ai)
2025-07-02 04:52:33.760 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.760 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.760 # compares by a factor of 3.
2025-07-02 04:52:33.760 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.760 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.760 # of the computation is cached by cruncher
2025-07-02 04:52:33.760 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.760 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.760 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.760 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.760 if best_ratio < cutoff:
2025-07-02 04:52:33.760 # no non-identical "pretty close" pair
2025-07-02 04:52:33.760 if eqi is None:
2025-07-02 04:52:33.760 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.760 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.760 return
2025-07-02 04:52:33.760 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.760 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.761 else:
2025-07-02 04:52:33.761 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.761 eqi = None
2025-07-02 04:52:33.761
2025-07-02 04:52:33.761 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.761 # identical
2025-07-02 04:52:33.761
2025-07-02 04:52:33.761 # pump out diffs from before the synch point
2025-07-02 04:52:33.761 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.761
2025-07-02 04:52:33.761 # do intraline marking on the synch pair
2025-07-02 04:52:33.761 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.761 if eqi is None:
2025-07-02 04:52:33.761 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.761 atags = btags = ""
2025-07-02 04:52:33.761 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.761 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.761 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.761 if tag == 'replace':
2025-07-02 04:52:33.761 atags += '^' * la
2025-07-02 04:52:33.761 btags += '^' * lb
2025-07-02 04:52:33.761 elif tag == 'delete':
2025-07-02 04:52:33.762 atags += '-' * la
2025-07-02 04:52:33.762 elif tag == 'insert':
2025-07-02 04:52:33.762 btags += '+' * lb
2025-07-02 04:52:33.762 elif tag == 'equal':
2025-07-02 04:52:33.762 atags += ' ' * la
2025-07-02 04:52:33.762 btags += ' ' * lb
2025-07-02 04:52:33.762 else:
2025-07-02 04:52:33.762 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.762 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.762 else:
2025-07-02 04:52:33.762 # the synch pair is identical
2025-07-02 04:52:33.762 yield ' ' + aelt
2025-07-02 04:52:33.762
2025-07-02 04:52:33.762 # pump out diffs from after the synch point
2025-07-02 04:52:33.762 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.762
2025-07-02 04:52:33.762 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.762 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.762
2025-07-02 04:52:33.762 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.763 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.763 alo = 467, ahi = 1101
2025-07-02 04:52:33.763 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.763 blo = 467, bhi = 1101
2025-07-02 04:52:33.763
2025-07-02 04:52:33.763 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.763 g = []
2025-07-02 04:52:33.763 if alo < ahi:
2025-07-02 04:52:33.763 if blo < bhi:
2025-07-02 04:52:33.763 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.763 else:
2025-07-02 04:52:33.763 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.763 elif blo < bhi:
2025-07-02 04:52:33.763 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.763
2025-07-02 04:52:33.763 > yield from g
2025-07-02 04:52:33.763
2025-07-02 04:52:33.763 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.763 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.763
2025-07-02 04:52:33.764 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.764 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.764 alo = 467, ahi = 1101
2025-07-02 04:52:33.764 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.764 blo = 467, bhi = 1101
2025-07-02 04:52:33.764
2025-07-02 04:52:33.764 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.764 r"""
2025-07-02 04:52:33.764 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.764 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.764 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.764 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.764
2025-07-02 04:52:33.764 Example:
2025-07-02 04:52:33.764
2025-07-02 04:52:33.764 >>> d = Differ()
2025-07-02 04:52:33.764 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.764 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.764 >>> print(''.join(results), end="")
2025-07-02 04:52:33.764 - abcDefghiJkl
2025-07-02 04:52:33.765 + abcdefGhijkl
2025-07-02 04:52:33.765 """
2025-07-02 04:52:33.765
2025-07-02 04:52:33.765 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.765 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.765 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.765 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.765 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.765
2025-07-02 04:52:33.765 # search for the pair that matches best without being identical
2025-07-02 04:52:33.765 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.765 # on junk -- unless we have to)
2025-07-02 04:52:33.765 for j in range(blo, bhi):
2025-07-02 04:52:33.765 bj = b[j]
2025-07-02 04:52:33.765 cruncher.set_seq2(bj)
2025-07-02 04:52:33.765 for i in range(alo, ahi):
2025-07-02 04:52:33.765 ai = a[i]
2025-07-02 04:52:33.765 if ai == bj:
2025-07-02 04:52:33.765 if eqi is None:
2025-07-02 04:52:33.765 eqi, eqj = i, j
2025-07-02 04:52:33.766 continue
2025-07-02 04:52:33.766 cruncher.set_seq1(ai)
2025-07-02 04:52:33.766 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.766 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.766 # compares by a factor of 3.
2025-07-02 04:52:33.766 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.766 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.766 # of the computation is cached by cruncher
2025-07-02 04:52:33.766 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.766 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.766 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.766 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.766 if best_ratio < cutoff:
2025-07-02 04:52:33.766 # no non-identical "pretty close" pair
2025-07-02 04:52:33.766 if eqi is None:
2025-07-02 04:52:33.766 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.766 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.766 return
2025-07-02 04:52:33.766 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.766 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.766 else:
2025-07-02 04:52:33.766 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.767 eqi = None
2025-07-02 04:52:33.767
2025-07-02 04:52:33.767 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.767 # identical
2025-07-02 04:52:33.767
2025-07-02 04:52:33.767 # pump out diffs from before the synch point
2025-07-02 04:52:33.767 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.767
2025-07-02 04:52:33.767 # do intraline marking on the synch pair
2025-07-02 04:52:33.767 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.767 if eqi is None:
2025-07-02 04:52:33.767 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.767 atags = btags = ""
2025-07-02 04:52:33.767 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.767 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.767 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.767 if tag == 'replace':
2025-07-02 04:52:33.767 atags += '^' * la
2025-07-02 04:52:33.767 btags += '^' * lb
2025-07-02 04:52:33.767 elif tag == 'delete':
2025-07-02 04:52:33.767 atags += '-' * la
2025-07-02 04:52:33.768 elif tag == 'insert':
2025-07-02 04:52:33.768 btags += '+' * lb
2025-07-02 04:52:33.768 elif tag == 'equal':
2025-07-02 04:52:33.768 atags += ' ' * la
2025-07-02 04:52:33.768 btags += ' ' * lb
2025-07-02 04:52:33.768 else:
2025-07-02 04:52:33.768 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.768 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.768 else:
2025-07-02 04:52:33.768 # the synch pair is identical
2025-07-02 04:52:33.768 yield ' ' + aelt
2025-07-02 04:52:33.768
2025-07-02 04:52:33.768 # pump out diffs from after the synch point
2025-07-02 04:52:33.768 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.768
2025-07-02 04:52:33.768 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.768 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.768
2025-07-02 04:52:33.768 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.768 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.768 alo = 468, ahi = 1101
2025-07-02 04:52:33.768 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.769 blo = 468, bhi = 1101
2025-07-02 04:52:33.769
2025-07-02 04:52:33.769 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.769 g = []
2025-07-02 04:52:33.769 if alo < ahi:
2025-07-02 04:52:33.769 if blo < bhi:
2025-07-02 04:52:33.769 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.769 else:
2025-07-02 04:52:33.769 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.769 elif blo < bhi:
2025-07-02 04:52:33.769 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.769
2025-07-02 04:52:33.769 > yield from g
2025-07-02 04:52:33.769
2025-07-02 04:52:33.769 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.769 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.769
2025-07-02 04:52:33.769 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.769 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.769 alo = 468, ahi = 1101
2025-07-02 04:52:33.769 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.770 blo = 468, bhi = 1101
2025-07-02 04:52:33.770
2025-07-02 04:52:33.770 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.770 r"""
2025-07-02 04:52:33.770 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.770 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.770 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.770 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.770
2025-07-02 04:52:33.770 Example:
2025-07-02 04:52:33.770
2025-07-02 04:52:33.770 >>> d = Differ()
2025-07-02 04:52:33.770 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.770 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.770 >>> print(''.join(results), end="")
2025-07-02 04:52:33.770 - abcDefghiJkl
2025-07-02 04:52:33.770 + abcdefGhijkl
2025-07-02 04:52:33.770 """
2025-07-02 04:52:33.770
2025-07-02 04:52:33.771 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.771 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.771 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.771 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.771 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.771
2025-07-02 04:52:33.771 # search for the pair that matches best without being identical
2025-07-02 04:52:33.771 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.771 # on junk -- unless we have to)
2025-07-02 04:52:33.771 for j in range(blo, bhi):
2025-07-02 04:52:33.771 bj = b[j]
2025-07-02 04:52:33.771 cruncher.set_seq2(bj)
2025-07-02 04:52:33.771 for i in range(alo, ahi):
2025-07-02 04:52:33.771 ai = a[i]
2025-07-02 04:52:33.771 if ai == bj:
2025-07-02 04:52:33.771 if eqi is None:
2025-07-02 04:52:33.771 eqi, eqj = i, j
2025-07-02 04:52:33.771 continue
2025-07-02 04:52:33.771 cruncher.set_seq1(ai)
2025-07-02 04:52:33.771 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.772 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.772 # compares by a factor of 3.
2025-07-02 04:52:33.772 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.772 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.772 # of the computation is cached by cruncher
2025-07-02 04:52:33.772 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.772 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.772 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.772 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.772 if best_ratio < cutoff:
2025-07-02 04:52:33.772 # no non-identical "pretty close" pair
2025-07-02 04:52:33.772 if eqi is None:
2025-07-02 04:52:33.772 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.772 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.772 return
2025-07-02 04:52:33.772 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.772 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.772 else:
2025-07-02 04:52:33.772 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.772 eqi = None
2025-07-02 04:52:33.772
2025-07-02 04:52:33.773 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.773 # identical
2025-07-02 04:52:33.773
2025-07-02 04:52:33.773 # pump out diffs from before the synch point
2025-07-02 04:52:33.773 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.773
2025-07-02 04:52:33.773 # do intraline marking on the synch pair
2025-07-02 04:52:33.773 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.773 if eqi is None:
2025-07-02 04:52:33.773 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.773 atags = btags = ""
2025-07-02 04:52:33.773 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.773 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.773 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.773 if tag == 'replace':
2025-07-02 04:52:33.773 atags += '^' * la
2025-07-02 04:52:33.773 btags += '^' * lb
2025-07-02 04:52:33.773 elif tag == 'delete':
2025-07-02 04:52:33.773 atags += '-' * la
2025-07-02 04:52:33.773 elif tag == 'insert':
2025-07-02 04:52:33.773 btags += '+' * lb
2025-07-02 04:52:33.773 elif tag == 'equal':
2025-07-02 04:52:33.774 atags += ' ' * la
2025-07-02 04:52:33.774 btags += ' ' * lb
2025-07-02 04:52:33.774 else:
2025-07-02 04:52:33.774 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.774 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.774 else:
2025-07-02 04:52:33.774 # the synch pair is identical
2025-07-02 04:52:33.774 yield ' ' + aelt
2025-07-02 04:52:33.774
2025-07-02 04:52:33.774 # pump out diffs from after the synch point
2025-07-02 04:52:33.774 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.774
2025-07-02 04:52:33.774 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.774 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.774
2025-07-02 04:52:33.774 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.774 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.774 alo = 469, ahi = 1101
2025-07-02 04:52:33.774 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.774 blo = 469, bhi = 1101
2025-07-02 04:52:33.774
2025-07-02 04:52:33.775 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.775 g = []
2025-07-02 04:52:33.775 if alo < ahi:
2025-07-02 04:52:33.775 if blo < bhi:
2025-07-02 04:52:33.775 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.775 else:
2025-07-02 04:52:33.775 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.775 elif blo < bhi:
2025-07-02 04:52:33.775 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.775
2025-07-02 04:52:33.775 > yield from g
2025-07-02 04:52:33.775
2025-07-02 04:52:33.775 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.775 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.775
2025-07-02 04:52:33.775 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.775 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.775 alo = 469, ahi = 1101
2025-07-02 04:52:33.775 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.775 blo = 469, bhi = 1101
2025-07-02 04:52:33.775
2025-07-02 04:52:33.775 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.776 r"""
2025-07-02 04:52:33.776 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.776 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.776 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.776 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.776
2025-07-02 04:52:33.776 Example:
2025-07-02 04:52:33.776
2025-07-02 04:52:33.776 >>> d = Differ()
2025-07-02 04:52:33.776 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.776 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.776 >>> print(''.join(results), end="")
2025-07-02 04:52:33.776 - abcDefghiJkl
2025-07-02 04:52:33.776 + abcdefGhijkl
2025-07-02 04:52:33.776 """
2025-07-02 04:52:33.776
2025-07-02 04:52:33.776 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.776 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.776 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.777 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.777 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.777
2025-07-02 04:52:33.777 # search for the pair that matches best without being identical
2025-07-02 04:52:33.777 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.777 # on junk -- unless we have to)
2025-07-02 04:52:33.777 for j in range(blo, bhi):
2025-07-02 04:52:33.777 bj = b[j]
2025-07-02 04:52:33.777 cruncher.set_seq2(bj)
2025-07-02 04:52:33.777 for i in range(alo, ahi):
2025-07-02 04:52:33.777 ai = a[i]
2025-07-02 04:52:33.777 if ai == bj:
2025-07-02 04:52:33.777 if eqi is None:
2025-07-02 04:52:33.777 eqi, eqj = i, j
2025-07-02 04:52:33.777 continue
2025-07-02 04:52:33.777 cruncher.set_seq1(ai)
2025-07-02 04:52:33.777 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.777 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.777 # compares by a factor of 3.
2025-07-02 04:52:33.777 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.777 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.777 # of the computation is cached by cruncher
2025-07-02 04:52:33.778 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.778 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.778 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.778 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.778 if best_ratio < cutoff:
2025-07-02 04:52:33.778 # no non-identical "pretty close" pair
2025-07-02 04:52:33.778 if eqi is None:
2025-07-02 04:52:33.778 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.778 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.778 return
2025-07-02 04:52:33.778 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.778 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.778 else:
2025-07-02 04:52:33.778 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.778 eqi = None
2025-07-02 04:52:33.778
2025-07-02 04:52:33.778 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.778 # identical
2025-07-02 04:52:33.779
2025-07-02 04:52:33.779 # pump out diffs from before the synch point
2025-07-02 04:52:33.779 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.779
2025-07-02 04:52:33.779 # do intraline marking on the synch pair
2025-07-02 04:52:33.779 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.779 if eqi is None:
2025-07-02 04:52:33.779 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.779 atags = btags = ""
2025-07-02 04:52:33.779 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.779 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.779 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.779 if tag == 'replace':
2025-07-02 04:52:33.779 atags += '^' * la
2025-07-02 04:52:33.779 btags += '^' * lb
2025-07-02 04:52:33.779 elif tag == 'delete':
2025-07-02 04:52:33.779 atags += '-' * la
2025-07-02 04:52:33.779 elif tag == 'insert':
2025-07-02 04:52:33.779 btags += '+' * lb
2025-07-02 04:52:33.779 elif tag == 'equal':
2025-07-02 04:52:33.779 atags += ' ' * la
2025-07-02 04:52:33.780 btags += ' ' * lb
2025-07-02 04:52:33.780 else:
2025-07-02 04:52:33.780 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.780 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.780 else:
2025-07-02 04:52:33.780 # the synch pair is identical
2025-07-02 04:52:33.780 yield ' ' + aelt
2025-07-02 04:52:33.780
2025-07-02 04:52:33.780 # pump out diffs from after the synch point
2025-07-02 04:52:33.780 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.780
2025-07-02 04:52:33.780 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.780 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.780
2025-07-02 04:52:33.780 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.780 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.780 alo = 470, ahi = 1101
2025-07-02 04:52:33.780 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.780 blo = 470, bhi = 1101
2025-07-02 04:52:33.780
2025-07-02 04:52:33.781 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.781 g = []
2025-07-02 04:52:33.781 if alo < ahi:
2025-07-02 04:52:33.781 if blo < bhi:
2025-07-02 04:52:33.781 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.781 else:
2025-07-02 04:52:33.781 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.781 elif blo < bhi:
2025-07-02 04:52:33.781 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.781
2025-07-02 04:52:33.781 > yield from g
2025-07-02 04:52:33.781
2025-07-02 04:52:33.781 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.781 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.781
2025-07-02 04:52:33.781 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.781 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.781 alo = 470, ahi = 1101
2025-07-02 04:52:33.782 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.782 blo = 470, bhi = 1101
2025-07-02 04:52:33.782
2025-07-02 04:52:33.782 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.782 r"""
2025-07-02 04:52:33.782 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.782 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.782 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.782 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.782
2025-07-02 04:52:33.782 Example:
2025-07-02 04:52:33.782
2025-07-02 04:52:33.782 >>> d = Differ()
2025-07-02 04:52:33.782 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.782 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.782 >>> print(''.join(results), end="")
2025-07-02 04:52:33.782 - abcDefghiJkl
2025-07-02 04:52:33.782 + abcdefGhijkl
2025-07-02 04:52:33.783 """
2025-07-02 04:52:33.783
2025-07-02 04:52:33.783 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.783 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.783 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.783 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.783 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.783
2025-07-02 04:52:33.783 # search for the pair that matches best without being identical
2025-07-02 04:52:33.783 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.783 # on junk -- unless we have to)
2025-07-02 04:52:33.783 for j in range(blo, bhi):
2025-07-02 04:52:33.783 bj = b[j]
2025-07-02 04:52:33.783 cruncher.set_seq2(bj)
2025-07-02 04:52:33.783 for i in range(alo, ahi):
2025-07-02 04:52:33.783 ai = a[i]
2025-07-02 04:52:33.783 if ai == bj:
2025-07-02 04:52:33.783 if eqi is None:
2025-07-02 04:52:33.783 eqi, eqj = i, j
2025-07-02 04:52:33.784 continue
2025-07-02 04:52:33.784 cruncher.set_seq1(ai)
2025-07-02 04:52:33.784 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.784 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.784 # compares by a factor of 3.
2025-07-02 04:52:33.784 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.784 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.784 # of the computation is cached by cruncher
2025-07-02 04:52:33.784 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.784 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.784 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.784 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.784 if best_ratio < cutoff:
2025-07-02 04:52:33.784 # no non-identical "pretty close" pair
2025-07-02 04:52:33.784 if eqi is None:
2025-07-02 04:52:33.784 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.784 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.784 return
2025-07-02 04:52:33.784 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.785 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.785 else:
2025-07-02 04:52:33.785 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.785 eqi = None
2025-07-02 04:52:33.785
2025-07-02 04:52:33.785 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.785 # identical
2025-07-02 04:52:33.785
2025-07-02 04:52:33.785 # pump out diffs from before the synch point
2025-07-02 04:52:33.785 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.785
2025-07-02 04:52:33.785 # do intraline marking on the synch pair
2025-07-02 04:52:33.785 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.785 if eqi is None:
2025-07-02 04:52:33.785 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.785 atags = btags = ""
2025-07-02 04:52:33.785 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.785 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.785 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.785 if tag == 'replace':
2025-07-02 04:52:33.786 atags += '^' * la
2025-07-02 04:52:33.786 btags += '^' * lb
2025-07-02 04:52:33.786 elif tag == 'delete':
2025-07-02 04:52:33.786 atags += '-' * la
2025-07-02 04:52:33.786 elif tag == 'insert':
2025-07-02 04:52:33.786 btags += '+' * lb
2025-07-02 04:52:33.786 elif tag == 'equal':
2025-07-02 04:52:33.786 atags += ' ' * la
2025-07-02 04:52:33.786 btags += ' ' * lb
2025-07-02 04:52:33.786 else:
2025-07-02 04:52:33.786 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.786 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.786 else:
2025-07-02 04:52:33.786 # the synch pair is identical
2025-07-02 04:52:33.786 yield ' ' + aelt
2025-07-02 04:52:33.786
2025-07-02 04:52:33.786 # pump out diffs from after the synch point
2025-07-02 04:52:33.786 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.787
2025-07-02 04:52:33.787 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.787 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.787
2025-07-02 04:52:33.787 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.787 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.787 alo = 471, ahi = 1101
2025-07-02 04:52:33.787 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.787 blo = 471, bhi = 1101
2025-07-02 04:52:33.787
2025-07-02 04:52:33.787 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.787 g = []
2025-07-02 04:52:33.787 if alo < ahi:
2025-07-02 04:52:33.787 if blo < bhi:
2025-07-02 04:52:33.787 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.787 else:
2025-07-02 04:52:33.787 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.787 elif blo < bhi:
2025-07-02 04:52:33.788 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.788
2025-07-02 04:52:33.788 > yield from g
2025-07-02 04:52:33.788
2025-07-02 04:52:33.788 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.788 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.788
2025-07-02 04:52:33.788 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.788 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.788 alo = 471, ahi = 1101
2025-07-02 04:52:33.788 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.788 blo = 471, bhi = 1101
2025-07-02 04:52:33.788
2025-07-02 04:52:33.788 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.788 r"""
2025-07-02 04:52:33.788 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.788 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.788 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.788 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.788
2025-07-02 04:52:33.789 Example:
2025-07-02 04:52:33.789
2025-07-02 04:52:33.789 >>> d = Differ()
2025-07-02 04:52:33.789 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.789 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.789 >>> print(''.join(results), end="")
2025-07-02 04:52:33.789 - abcDefghiJkl
2025-07-02 04:52:33.789 + abcdefGhijkl
2025-07-02 04:52:33.789 """
2025-07-02 04:52:33.789
2025-07-02 04:52:33.789 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.789 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.789 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.789 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.789 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.789
2025-07-02 04:52:33.789 # search for the pair that matches best without being identical
2025-07-02 04:52:33.789 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.790 # on junk -- unless we have to)
2025-07-02 04:52:33.790 for j in range(blo, bhi):
2025-07-02 04:52:33.790 bj = b[j]
2025-07-02 04:52:33.790 cruncher.set_seq2(bj)
2025-07-02 04:52:33.790 for i in range(alo, ahi):
2025-07-02 04:52:33.790 ai = a[i]
2025-07-02 04:52:33.790 if ai == bj:
2025-07-02 04:52:33.790 if eqi is None:
2025-07-02 04:52:33.790 eqi, eqj = i, j
2025-07-02 04:52:33.790 continue
2025-07-02 04:52:33.790 cruncher.set_seq1(ai)
2025-07-02 04:52:33.790 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.790 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.790 # compares by a factor of 3.
2025-07-02 04:52:33.790 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.790 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.790 # of the computation is cached by cruncher
2025-07-02 04:52:33.790 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.790 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.790 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.790 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.790 if best_ratio < cutoff:
2025-07-02 04:52:33.791 # no non-identical "pretty close" pair
2025-07-02 04:52:33.791 if eqi is None:
2025-07-02 04:52:33.791 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.791 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.791 return
2025-07-02 04:52:33.791 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.791 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.791 else:
2025-07-02 04:52:33.791 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.791 eqi = None
2025-07-02 04:52:33.791
2025-07-02 04:52:33.791 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.791 # identical
2025-07-02 04:52:33.791
2025-07-02 04:52:33.791 # pump out diffs from before the synch point
2025-07-02 04:52:33.791 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.791
2025-07-02 04:52:33.791 # do intraline marking on the synch pair
2025-07-02 04:52:33.791 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.791 if eqi is None:
2025-07-02 04:52:33.791 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.792 atags = btags = ""
2025-07-02 04:52:33.792 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.792 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.792 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.792 if tag == 'replace':
2025-07-02 04:52:33.792 atags += '^' * la
2025-07-02 04:52:33.792 btags += '^' * lb
2025-07-02 04:52:33.792 elif tag == 'delete':
2025-07-02 04:52:33.792 atags += '-' * la
2025-07-02 04:52:33.792 elif tag == 'insert':
2025-07-02 04:52:33.792 btags += '+' * lb
2025-07-02 04:52:33.792 elif tag == 'equal':
2025-07-02 04:52:33.792 atags += ' ' * la
2025-07-02 04:52:33.792 btags += ' ' * lb
2025-07-02 04:52:33.792 else:
2025-07-02 04:52:33.792 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.792 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.792 else:
2025-07-02 04:52:33.792 # the synch pair is identical
2025-07-02 04:52:33.792 yield ' ' + aelt
2025-07-02 04:52:33.792
2025-07-02 04:52:33.792 # pump out diffs from after the synch point
2025-07-02 04:52:33.793 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.793
2025-07-02 04:52:33.793 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.793 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.793
2025-07-02 04:52:33.793 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.793 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.793 alo = 472, ahi = 1101
2025-07-02 04:52:33.793 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.793 blo = 472, bhi = 1101
2025-07-02 04:52:33.793
2025-07-02 04:52:33.793 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.793 g = []
2025-07-02 04:52:33.793 if alo < ahi:
2025-07-02 04:52:33.793 if blo < bhi:
2025-07-02 04:52:33.793 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.793 else:
2025-07-02 04:52:33.793 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.793 elif blo < bhi:
2025-07-02 04:52:33.794 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.794
2025-07-02 04:52:33.794 > yield from g
2025-07-02 04:52:33.794
2025-07-02 04:52:33.794 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.794 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.794
2025-07-02 04:52:33.794 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.794 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.794 alo = 472, ahi = 1101
2025-07-02 04:52:33.794 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.794 blo = 472, bhi = 1101
2025-07-02 04:52:33.794
2025-07-02 04:52:33.794 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.794 r"""
2025-07-02 04:52:33.794 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.794 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.794 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.794 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.794
2025-07-02 04:52:33.794 Example:
2025-07-02 04:52:33.795
2025-07-02 04:52:33.795 >>> d = Differ()
2025-07-02 04:52:33.795 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.795 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.795 >>> print(''.join(results), end="")
2025-07-02 04:52:33.795 - abcDefghiJkl
2025-07-02 04:52:33.795 + abcdefGhijkl
2025-07-02 04:52:33.795 """
2025-07-02 04:52:33.795
2025-07-02 04:52:33.795 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.795 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.795 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.795 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.795 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.795
2025-07-02 04:52:33.795 # search for the pair that matches best without being identical
2025-07-02 04:52:33.795 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.795 # on junk -- unless we have to)
2025-07-02 04:52:33.795 for j in range(blo, bhi):
2025-07-02 04:52:33.796 bj = b[j]
2025-07-02 04:52:33.796 cruncher.set_seq2(bj)
2025-07-02 04:52:33.796 for i in range(alo, ahi):
2025-07-02 04:52:33.796 ai = a[i]
2025-07-02 04:52:33.796 if ai == bj:
2025-07-02 04:52:33.796 if eqi is None:
2025-07-02 04:52:33.796 eqi, eqj = i, j
2025-07-02 04:52:33.796 continue
2025-07-02 04:52:33.796 cruncher.set_seq1(ai)
2025-07-02 04:52:33.796 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.796 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.796 # compares by a factor of 3.
2025-07-02 04:52:33.796 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.796 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.796 # of the computation is cached by cruncher
2025-07-02 04:52:33.796 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.796 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.796 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.796 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.797 if best_ratio < cutoff:
2025-07-02 04:52:33.797 # no non-identical "pretty close" pair
2025-07-02 04:52:33.797 if eqi is None:
2025-07-02 04:52:33.797 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.797 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.797 return
2025-07-02 04:52:33.797 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.797 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.797 else:
2025-07-02 04:52:33.797 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.797 eqi = None
2025-07-02 04:52:33.797
2025-07-02 04:52:33.797 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.797 # identical
2025-07-02 04:52:33.797
2025-07-02 04:52:33.797 # pump out diffs from before the synch point
2025-07-02 04:52:33.797 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.797
2025-07-02 04:52:33.797 # do intraline marking on the synch pair
2025-07-02 04:52:33.797 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.798 if eqi is None:
2025-07-02 04:52:33.798 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.798 atags = btags = ""
2025-07-02 04:52:33.798 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.798 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.798 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.798 if tag == 'replace':
2025-07-02 04:52:33.798 atags += '^' * la
2025-07-02 04:52:33.798 btags += '^' * lb
2025-07-02 04:52:33.798 elif tag == 'delete':
2025-07-02 04:52:33.798 atags += '-' * la
2025-07-02 04:52:33.798 elif tag == 'insert':
2025-07-02 04:52:33.798 btags += '+' * lb
2025-07-02 04:52:33.798 elif tag == 'equal':
2025-07-02 04:52:33.798 atags += ' ' * la
2025-07-02 04:52:33.798 btags += ' ' * lb
2025-07-02 04:52:33.798 else:
2025-07-02 04:52:33.798 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.798 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.798 else:
2025-07-02 04:52:33.798 # the synch pair is identical
2025-07-02 04:52:33.799 yield ' ' + aelt
2025-07-02 04:52:33.799
2025-07-02 04:52:33.799 # pump out diffs from after the synch point
2025-07-02 04:52:33.799 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.799
2025-07-02 04:52:33.799 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.799 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.799
2025-07-02 04:52:33.799 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.799 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.799 alo = 473, ahi = 1101
2025-07-02 04:52:33.799 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.799 blo = 473, bhi = 1101
2025-07-02 04:52:33.799
2025-07-02 04:52:33.799 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.799 g = []
2025-07-02 04:52:33.799 if alo < ahi:
2025-07-02 04:52:33.799 if blo < bhi:
2025-07-02 04:52:33.799 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.799 else:
2025-07-02 04:52:33.799 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.800 elif blo < bhi:
2025-07-02 04:52:33.800 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.800
2025-07-02 04:52:33.800 > yield from g
2025-07-02 04:52:33.800
2025-07-02 04:52:33.800 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.800 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.800
2025-07-02 04:52:33.800 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.800 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.800 alo = 473, ahi = 1101
2025-07-02 04:52:33.800 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.800 blo = 473, bhi = 1101
2025-07-02 04:52:33.800
2025-07-02 04:52:33.800 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.800 r"""
2025-07-02 04:52:33.800 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.800 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.800 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.800 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.800
2025-07-02 04:52:33.801 Example:
2025-07-02 04:52:33.801
2025-07-02 04:52:33.801 >>> d = Differ()
2025-07-02 04:52:33.801 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.801 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.801 >>> print(''.join(results), end="")
2025-07-02 04:52:33.801 - abcDefghiJkl
2025-07-02 04:52:33.801 + abcdefGhijkl
2025-07-02 04:52:33.801 """
2025-07-02 04:52:33.801
2025-07-02 04:52:33.801 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.801 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.801 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.801 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.801 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.801
2025-07-02 04:52:33.801 # search for the pair that matches best without being identical
2025-07-02 04:52:33.801 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.801 # on junk -- unless we have to)
2025-07-02 04:52:33.801 for j in range(blo, bhi):
2025-07-02 04:52:33.802 bj = b[j]
2025-07-02 04:52:33.802 cruncher.set_seq2(bj)
2025-07-02 04:52:33.802 for i in range(alo, ahi):
2025-07-02 04:52:33.802 ai = a[i]
2025-07-02 04:52:33.802 if ai == bj:
2025-07-02 04:52:33.802 if eqi is None:
2025-07-02 04:52:33.802 eqi, eqj = i, j
2025-07-02 04:52:33.802 continue
2025-07-02 04:52:33.802 cruncher.set_seq1(ai)
2025-07-02 04:52:33.802 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.802 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.802 # compares by a factor of 3.
2025-07-02 04:52:33.802 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.802 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.802 # of the computation is cached by cruncher
2025-07-02 04:52:33.802 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.802 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.802 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.802 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.802 if best_ratio < cutoff:
2025-07-02 04:52:33.802 # no non-identical "pretty close" pair
2025-07-02 04:52:33.803 if eqi is None:
2025-07-02 04:52:33.803 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.803 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.803 return
2025-07-02 04:52:33.803 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.803 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.803 else:
2025-07-02 04:52:33.803 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.803 eqi = None
2025-07-02 04:52:33.803
2025-07-02 04:52:33.803 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.803 # identical
2025-07-02 04:52:33.803
2025-07-02 04:52:33.803 # pump out diffs from before the synch point
2025-07-02 04:52:33.803 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.803
2025-07-02 04:52:33.803 # do intraline marking on the synch pair
2025-07-02 04:52:33.803 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.803 if eqi is None:
2025-07-02 04:52:33.803 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.803 atags = btags = ""
2025-07-02 04:52:33.803 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.804 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.804 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.804 if tag == 'replace':
2025-07-02 04:52:33.804 atags += '^' * la
2025-07-02 04:52:33.804 btags += '^' * lb
2025-07-02 04:52:33.804 elif tag == 'delete':
2025-07-02 04:52:33.804 atags += '-' * la
2025-07-02 04:52:33.804 elif tag == 'insert':
2025-07-02 04:52:33.804 btags += '+' * lb
2025-07-02 04:52:33.804 elif tag == 'equal':
2025-07-02 04:52:33.804 atags += ' ' * la
2025-07-02 04:52:33.804 btags += ' ' * lb
2025-07-02 04:52:33.804 else:
2025-07-02 04:52:33.804 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.804 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.804 else:
2025-07-02 04:52:33.804 # the synch pair is identical
2025-07-02 04:52:33.804 yield ' ' + aelt
2025-07-02 04:52:33.804
2025-07-02 04:52:33.804 # pump out diffs from after the synch point
2025-07-02 04:52:33.805 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.805
2025-07-02 04:52:33.805 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.805 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.805
2025-07-02 04:52:33.805 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.805 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.805 alo = 474, ahi = 1101
2025-07-02 04:52:33.805 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.805 blo = 474, bhi = 1101
2025-07-02 04:52:33.805
2025-07-02 04:52:33.805 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.805 g = []
2025-07-02 04:52:33.805 if alo < ahi:
2025-07-02 04:52:33.805 if blo < bhi:
2025-07-02 04:52:33.805 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.805 else:
2025-07-02 04:52:33.805 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.805 elif blo < bhi:
2025-07-02 04:52:33.805 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.805
2025-07-02 04:52:33.806 > yield from g
2025-07-02 04:52:33.806
2025-07-02 04:52:33.806 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.806 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.806
2025-07-02 04:52:33.806 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.806 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.806 alo = 474, ahi = 1101
2025-07-02 04:52:33.806 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.806 blo = 474, bhi = 1101
2025-07-02 04:52:33.806
2025-07-02 04:52:33.806 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.806 r"""
2025-07-02 04:52:33.806 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.806 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.806 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.806 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.806
2025-07-02 04:52:33.806 Example:
2025-07-02 04:52:33.806
2025-07-02 04:52:33.807 >>> d = Differ()
2025-07-02 04:52:33.807 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.807 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.807 >>> print(''.join(results), end="")
2025-07-02 04:52:33.807 - abcDefghiJkl
2025-07-02 04:52:33.807 + abcdefGhijkl
2025-07-02 04:52:33.807 """
2025-07-02 04:52:33.807
2025-07-02 04:52:33.807 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.807 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.807 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.807 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.807 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.807
2025-07-02 04:52:33.807 # search for the pair that matches best without being identical
2025-07-02 04:52:33.807 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.807 # on junk -- unless we have to)
2025-07-02 04:52:33.807 for j in range(blo, bhi):
2025-07-02 04:52:33.807 bj = b[j]
2025-07-02 04:52:33.807 cruncher.set_seq2(bj)
2025-07-02 04:52:33.808 for i in range(alo, ahi):
2025-07-02 04:52:33.808 ai = a[i]
2025-07-02 04:52:33.808 if ai == bj:
2025-07-02 04:52:33.808 if eqi is None:
2025-07-02 04:52:33.808 eqi, eqj = i, j
2025-07-02 04:52:33.808 continue
2025-07-02 04:52:33.808 cruncher.set_seq1(ai)
2025-07-02 04:52:33.808 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.808 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.808 # compares by a factor of 3.
2025-07-02 04:52:33.808 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.808 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.808 # of the computation is cached by cruncher
2025-07-02 04:52:33.808 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.808 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.808 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.808 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.808 if best_ratio < cutoff:
2025-07-02 04:52:33.808 # no non-identical "pretty close" pair
2025-07-02 04:52:33.809 if eqi is None:
2025-07-02 04:52:33.809 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.809 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.809 return
2025-07-02 04:52:33.809 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.809 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.809 else:
2025-07-02 04:52:33.809 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.809 eqi = None
2025-07-02 04:52:33.809
2025-07-02 04:52:33.809 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.809 # identical
2025-07-02 04:52:33.809
2025-07-02 04:52:33.809 # pump out diffs from before the synch point
2025-07-02 04:52:33.809 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.809
2025-07-02 04:52:33.809 # do intraline marking on the synch pair
2025-07-02 04:52:33.809 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.809 if eqi is None:
2025-07-02 04:52:33.809 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.809 atags = btags = ""
2025-07-02 04:52:33.810 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.810 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.810 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.810 if tag == 'replace':
2025-07-02 04:52:33.810 atags += '^' * la
2025-07-02 04:52:33.810 btags += '^' * lb
2025-07-02 04:52:33.810 elif tag == 'delete':
2025-07-02 04:52:33.810 atags += '-' * la
2025-07-02 04:52:33.810 elif tag == 'insert':
2025-07-02 04:52:33.810 btags += '+' * lb
2025-07-02 04:52:33.810 elif tag == 'equal':
2025-07-02 04:52:33.810 atags += ' ' * la
2025-07-02 04:52:33.810 btags += ' ' * lb
2025-07-02 04:52:33.810 else:
2025-07-02 04:52:33.810 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.810 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.810 else:
2025-07-02 04:52:33.810 # the synch pair is identical
2025-07-02 04:52:33.810 yield ' ' + aelt
2025-07-02 04:52:33.810
2025-07-02 04:52:33.810 # pump out diffs from after the synch point
2025-07-02 04:52:33.811 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.811
2025-07-02 04:52:33.811 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.811 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.811
2025-07-02 04:52:33.811 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.811 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.811 alo = 475, ahi = 1101
2025-07-02 04:52:33.811 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.811 blo = 475, bhi = 1101
2025-07-02 04:52:33.811
2025-07-02 04:52:33.811 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.811 g = []
2025-07-02 04:52:33.811 if alo < ahi:
2025-07-02 04:52:33.811 if blo < bhi:
2025-07-02 04:52:33.811 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.811 else:
2025-07-02 04:52:33.811 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.811 elif blo < bhi:
2025-07-02 04:52:33.811 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.811
2025-07-02 04:52:33.812 > yield from g
2025-07-02 04:52:33.812
2025-07-02 04:52:33.812 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.812 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.812
2025-07-02 04:52:33.812 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.812 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.812 alo = 475, ahi = 1101
2025-07-02 04:52:33.812 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.812 blo = 475, bhi = 1101
2025-07-02 04:52:33.812
2025-07-02 04:52:33.812 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.812 r"""
2025-07-02 04:52:33.812 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.812 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.812 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.812 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.812
2025-07-02 04:52:33.812 Example:
2025-07-02 04:52:33.813
2025-07-02 04:52:33.813 >>> d = Differ()
2025-07-02 04:52:33.813 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.813 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.813 >>> print(''.join(results), end="")
2025-07-02 04:52:33.813 - abcDefghiJkl
2025-07-02 04:52:33.813 + abcdefGhijkl
2025-07-02 04:52:33.813 """
2025-07-02 04:52:33.813
2025-07-02 04:52:33.813 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.813 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.813 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.813 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.813 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.813
2025-07-02 04:52:33.813 # search for the pair that matches best without being identical
2025-07-02 04:52:33.813 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.813 # on junk -- unless we have to)
2025-07-02 04:52:33.813 for j in range(blo, bhi):
2025-07-02 04:52:33.814 bj = b[j]
2025-07-02 04:52:33.814 cruncher.set_seq2(bj)
2025-07-02 04:52:33.814 for i in range(alo, ahi):
2025-07-02 04:52:33.814 ai = a[i]
2025-07-02 04:52:33.814 if ai == bj:
2025-07-02 04:52:33.814 if eqi is None:
2025-07-02 04:52:33.814 eqi, eqj = i, j
2025-07-02 04:52:33.814 continue
2025-07-02 04:52:33.814 cruncher.set_seq1(ai)
2025-07-02 04:52:33.814 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.814 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.814 # compares by a factor of 3.
2025-07-02 04:52:33.814 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.814 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.814 # of the computation is cached by cruncher
2025-07-02 04:52:33.814 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.814 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.814 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.814 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.814 if best_ratio < cutoff:
2025-07-02 04:52:33.815 # no non-identical "pretty close" pair
2025-07-02 04:52:33.815 if eqi is None:
2025-07-02 04:52:33.815 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.815 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.815 return
2025-07-02 04:52:33.815 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.815 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.815 else:
2025-07-02 04:52:33.815 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.815 eqi = None
2025-07-02 04:52:33.815
2025-07-02 04:52:33.815 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.815 # identical
2025-07-02 04:52:33.815
2025-07-02 04:52:33.815 # pump out diffs from before the synch point
2025-07-02 04:52:33.815 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.815
2025-07-02 04:52:33.815 # do intraline marking on the synch pair
2025-07-02 04:52:33.815 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.815 if eqi is None:
2025-07-02 04:52:33.815 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.815 atags = btags = ""
2025-07-02 04:52:33.816 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.816 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.816 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.816 if tag == 'replace':
2025-07-02 04:52:33.816 atags += '^' * la
2025-07-02 04:52:33.816 btags += '^' * lb
2025-07-02 04:52:33.816 elif tag == 'delete':
2025-07-02 04:52:33.816 atags += '-' * la
2025-07-02 04:52:33.816 elif tag == 'insert':
2025-07-02 04:52:33.816 btags += '+' * lb
2025-07-02 04:52:33.816 elif tag == 'equal':
2025-07-02 04:52:33.816 atags += ' ' * la
2025-07-02 04:52:33.816 btags += ' ' * lb
2025-07-02 04:52:33.816 else:
2025-07-02 04:52:33.816 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.816 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.816 else:
2025-07-02 04:52:33.816 # the synch pair is identical
2025-07-02 04:52:33.816 yield ' ' + aelt
2025-07-02 04:52:33.816
2025-07-02 04:52:33.816 # pump out diffs from after the synch point
2025-07-02 04:52:33.816 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.817
2025-07-02 04:52:33.817 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.817 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.817
2025-07-02 04:52:33.817 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.817 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.817 alo = 476, ahi = 1101
2025-07-02 04:52:33.817 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.817 blo = 476, bhi = 1101
2025-07-02 04:52:33.817
2025-07-02 04:52:33.817 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.817 g = []
2025-07-02 04:52:33.817 if alo < ahi:
2025-07-02 04:52:33.817 if blo < bhi:
2025-07-02 04:52:33.817 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.817 else:
2025-07-02 04:52:33.817 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.817 elif blo < bhi:
2025-07-02 04:52:33.817 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.817
2025-07-02 04:52:33.817 > yield from g
2025-07-02 04:52:33.818
2025-07-02 04:52:33.818 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.818 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.818
2025-07-02 04:52:33.818 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.818 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.818 alo = 476, ahi = 1101
2025-07-02 04:52:33.818 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.818 blo = 476, bhi = 1101
2025-07-02 04:52:33.818
2025-07-02 04:52:33.818 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.818 r"""
2025-07-02 04:52:33.818 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.818 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.818 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.818 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.818
2025-07-02 04:52:33.818 Example:
2025-07-02 04:52:33.818
2025-07-02 04:52:33.818 >>> d = Differ()
2025-07-02 04:52:33.818 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.819 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.819 >>> print(''.join(results), end="")
2025-07-02 04:52:33.819 - abcDefghiJkl
2025-07-02 04:52:33.819 + abcdefGhijkl
2025-07-02 04:52:33.819 """
2025-07-02 04:52:33.819
2025-07-02 04:52:33.819 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.819 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.819 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.819 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.819 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.819
2025-07-02 04:52:33.819 # search for the pair that matches best without being identical
2025-07-02 04:52:33.819 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.819 # on junk -- unless we have to)
2025-07-02 04:52:33.819 for j in range(blo, bhi):
2025-07-02 04:52:33.819 bj = b[j]
2025-07-02 04:52:33.819 cruncher.set_seq2(bj)
2025-07-02 04:52:33.819 for i in range(alo, ahi):
2025-07-02 04:52:33.819 ai = a[i]
2025-07-02 04:52:33.820 if ai == bj:
2025-07-02 04:52:33.820 if eqi is None:
2025-07-02 04:52:33.820 eqi, eqj = i, j
2025-07-02 04:52:33.820 continue
2025-07-02 04:52:33.820 cruncher.set_seq1(ai)
2025-07-02 04:52:33.820 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.820 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.820 # compares by a factor of 3.
2025-07-02 04:52:33.820 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.820 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.820 # of the computation is cached by cruncher
2025-07-02 04:52:33.820 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.820 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.820 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.820 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.820 if best_ratio < cutoff:
2025-07-02 04:52:33.820 # no non-identical "pretty close" pair
2025-07-02 04:52:33.820 if eqi is None:
2025-07-02 04:52:33.820 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.820 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.821 return
2025-07-02 04:52:33.821 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.821 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.821 else:
2025-07-02 04:52:33.821 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.821 eqi = None
2025-07-02 04:52:33.821
2025-07-02 04:52:33.821 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.821 # identical
2025-07-02 04:52:33.821
2025-07-02 04:52:33.821 # pump out diffs from before the synch point
2025-07-02 04:52:33.821 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.821
2025-07-02 04:52:33.821 # do intraline marking on the synch pair
2025-07-02 04:52:33.821 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.821 if eqi is None:
2025-07-02 04:52:33.821 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.821 atags = btags = ""
2025-07-02 04:52:33.821 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.821 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.821 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.822 if tag == 'replace':
2025-07-02 04:52:33.822 atags += '^' * la
2025-07-02 04:52:33.822 btags += '^' * lb
2025-07-02 04:52:33.822 elif tag == 'delete':
2025-07-02 04:52:33.822 atags += '-' * la
2025-07-02 04:52:33.822 elif tag == 'insert':
2025-07-02 04:52:33.822 btags += '+' * lb
2025-07-02 04:52:33.822 elif tag == 'equal':
2025-07-02 04:52:33.822 atags += ' ' * la
2025-07-02 04:52:33.822 btags += ' ' * lb
2025-07-02 04:52:33.822 else:
2025-07-02 04:52:33.822 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.822 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.822 else:
2025-07-02 04:52:33.822 # the synch pair is identical
2025-07-02 04:52:33.822 yield ' ' + aelt
2025-07-02 04:52:33.822
2025-07-02 04:52:33.822 # pump out diffs from after the synch point
2025-07-02 04:52:33.822 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.822
2025-07-02 04:52:33.822 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.823 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.823
2025-07-02 04:52:33.823 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.823 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.823 alo = 477, ahi = 1101
2025-07-02 04:52:33.823 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.823 blo = 477, bhi = 1101
2025-07-02 04:52:33.823
2025-07-02 04:52:33.823 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.823 g = []
2025-07-02 04:52:33.823 if alo < ahi:
2025-07-02 04:52:33.823 if blo < bhi:
2025-07-02 04:52:33.823 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.823 else:
2025-07-02 04:52:33.823 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.823 elif blo < bhi:
2025-07-02 04:52:33.823 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.823
2025-07-02 04:52:33.823 > yield from g
2025-07-02 04:52:33.823
2025-07-02 04:52:33.823 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.824 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.824
2025-07-02 04:52:33.824 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.824 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.824 alo = 477, ahi = 1101
2025-07-02 04:52:33.824 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.824 blo = 477, bhi = 1101
2025-07-02 04:52:33.824
2025-07-02 04:52:33.824 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.824 r"""
2025-07-02 04:52:33.824 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.824 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.824 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.824 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.824
2025-07-02 04:52:33.824 Example:
2025-07-02 04:52:33.824
2025-07-02 04:52:33.824 >>> d = Differ()
2025-07-02 04:52:33.824 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.825 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.825 >>> print(''.join(results), end="")
2025-07-02 04:52:33.825 - abcDefghiJkl
2025-07-02 04:52:33.825 + abcdefGhijkl
2025-07-02 04:52:33.825 """
2025-07-02 04:52:33.825
2025-07-02 04:52:33.825 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.825 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.825 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.825 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.825 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.825
2025-07-02 04:52:33.825 # search for the pair that matches best without being identical
2025-07-02 04:52:33.825 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.825 # on junk -- unless we have to)
2025-07-02 04:52:33.825 for j in range(blo, bhi):
2025-07-02 04:52:33.825 bj = b[j]
2025-07-02 04:52:33.825 cruncher.set_seq2(bj)
2025-07-02 04:52:33.825 for i in range(alo, ahi):
2025-07-02 04:52:33.826 ai = a[i]
2025-07-02 04:52:33.826 if ai == bj:
2025-07-02 04:52:33.826 if eqi is None:
2025-07-02 04:52:33.826 eqi, eqj = i, j
2025-07-02 04:52:33.826 continue
2025-07-02 04:52:33.826 cruncher.set_seq1(ai)
2025-07-02 04:52:33.826 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.826 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.826 # compares by a factor of 3.
2025-07-02 04:52:33.826 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.826 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.826 # of the computation is cached by cruncher
2025-07-02 04:52:33.826 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.826 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.826 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.826 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.826 if best_ratio < cutoff:
2025-07-02 04:52:33.826 # no non-identical "pretty close" pair
2025-07-02 04:52:33.826 if eqi is None:
2025-07-02 04:52:33.826 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.827 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.827 return
2025-07-02 04:52:33.827 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.827 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.827 else:
2025-07-02 04:52:33.827 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.827 eqi = None
2025-07-02 04:52:33.827
2025-07-02 04:52:33.827 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.827 # identical
2025-07-02 04:52:33.827
2025-07-02 04:52:33.827 # pump out diffs from before the synch point
2025-07-02 04:52:33.827 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.827
2025-07-02 04:52:33.827 # do intraline marking on the synch pair
2025-07-02 04:52:33.827 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.827 if eqi is None:
2025-07-02 04:52:33.827 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.827 atags = btags = ""
2025-07-02 04:52:33.827 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.828 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.828 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.828 if tag == 'replace':
2025-07-02 04:52:33.828 atags += '^' * la
2025-07-02 04:52:33.828 btags += '^' * lb
2025-07-02 04:52:33.828 elif tag == 'delete':
2025-07-02 04:52:33.828 atags += '-' * la
2025-07-02 04:52:33.828 elif tag == 'insert':
2025-07-02 04:52:33.828 btags += '+' * lb
2025-07-02 04:52:33.828 elif tag == 'equal':
2025-07-02 04:52:33.828 atags += ' ' * la
2025-07-02 04:52:33.828 btags += ' ' * lb
2025-07-02 04:52:33.828 else:
2025-07-02 04:52:33.828 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.828 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.828 else:
2025-07-02 04:52:33.828 # the synch pair is identical
2025-07-02 04:52:33.828 yield ' ' + aelt
2025-07-02 04:52:33.828
2025-07-02 04:52:33.828 # pump out diffs from after the synch point
2025-07-02 04:52:33.828 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.829
2025-07-02 04:52:33.829 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.829 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.829
2025-07-02 04:52:33.829 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.829 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.829 alo = 478, ahi = 1101
2025-07-02 04:52:33.829 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.829 blo = 478, bhi = 1101
2025-07-02 04:52:33.829
2025-07-02 04:52:33.829 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.829 g = []
2025-07-02 04:52:33.829 if alo < ahi:
2025-07-02 04:52:33.829 if blo < bhi:
2025-07-02 04:52:33.829 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.829 else:
2025-07-02 04:52:33.829 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.829 elif blo < bhi:
2025-07-02 04:52:33.830 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.830
2025-07-02 04:52:33.830 > yield from g
2025-07-02 04:52:33.830
2025-07-02 04:52:33.830 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.830 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.830
2025-07-02 04:52:33.830 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.830 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.830 alo = 478, ahi = 1101
2025-07-02 04:52:33.830 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.830 blo = 478, bhi = 1101
2025-07-02 04:52:33.830
2025-07-02 04:52:33.830 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.830 r"""
2025-07-02 04:52:33.830 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.830 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.830 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.830 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.830
2025-07-02 04:52:33.831 Example:
2025-07-02 04:52:33.831
2025-07-02 04:52:33.831 >>> d = Differ()
2025-07-02 04:52:33.831 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.831 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.831 >>> print(''.join(results), end="")
2025-07-02 04:52:33.831 - abcDefghiJkl
2025-07-02 04:52:33.831 + abcdefGhijkl
2025-07-02 04:52:33.831 """
2025-07-02 04:52:33.831
2025-07-02 04:52:33.831 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.831 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.831 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.831 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.831 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.831
2025-07-02 04:52:33.831 # search for the pair that matches best without being identical
2025-07-02 04:52:33.831 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.831 # on junk -- unless we have to)
2025-07-02 04:52:33.832 for j in range(blo, bhi):
2025-07-02 04:52:33.832 bj = b[j]
2025-07-02 04:52:33.832 cruncher.set_seq2(bj)
2025-07-02 04:52:33.832 for i in range(alo, ahi):
2025-07-02 04:52:33.832 ai = a[i]
2025-07-02 04:52:33.832 if ai == bj:
2025-07-02 04:52:33.832 if eqi is None:
2025-07-02 04:52:33.832 eqi, eqj = i, j
2025-07-02 04:52:33.832 continue
2025-07-02 04:52:33.832 cruncher.set_seq1(ai)
2025-07-02 04:52:33.832 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.832 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.832 # compares by a factor of 3.
2025-07-02 04:52:33.832 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.832 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.832 # of the computation is cached by cruncher
2025-07-02 04:52:33.832 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.832 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.832 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.832 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.832 if best_ratio < cutoff:
2025-07-02 04:52:33.833 # no non-identical "pretty close" pair
2025-07-02 04:52:33.833 if eqi is None:
2025-07-02 04:52:33.833 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.833 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.833 return
2025-07-02 04:52:33.833 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.833 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.833 else:
2025-07-02 04:52:33.833 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.833 eqi = None
2025-07-02 04:52:33.833
2025-07-02 04:52:33.833 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.833 # identical
2025-07-02 04:52:33.833
2025-07-02 04:52:33.833 # pump out diffs from before the synch point
2025-07-02 04:52:33.833 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.833
2025-07-02 04:52:33.833 # do intraline marking on the synch pair
2025-07-02 04:52:33.833 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.833 if eqi is None:
2025-07-02 04:52:33.833 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.834 atags = btags = ""
2025-07-02 04:52:33.834 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.834 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.834 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.834 if tag == 'replace':
2025-07-02 04:52:33.834 atags += '^' * la
2025-07-02 04:52:33.834 btags += '^' * lb
2025-07-02 04:52:33.834 elif tag == 'delete':
2025-07-02 04:52:33.834 atags += '-' * la
2025-07-02 04:52:33.834 elif tag == 'insert':
2025-07-02 04:52:33.834 btags += '+' * lb
2025-07-02 04:52:33.834 elif tag == 'equal':
2025-07-02 04:52:33.834 atags += ' ' * la
2025-07-02 04:52:33.834 btags += ' ' * lb
2025-07-02 04:52:33.834 else:
2025-07-02 04:52:33.834 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.834 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.834 else:
2025-07-02 04:52:33.834 # the synch pair is identical
2025-07-02 04:52:33.834 yield ' ' + aelt
2025-07-02 04:52:33.834
2025-07-02 04:52:33.834 # pump out diffs from after the synch point
2025-07-02 04:52:33.835 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.835
2025-07-02 04:52:33.835 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.835 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.835
2025-07-02 04:52:33.835 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.835 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.835 alo = 479, ahi = 1101
2025-07-02 04:52:33.835 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.835 blo = 479, bhi = 1101
2025-07-02 04:52:33.835
2025-07-02 04:52:33.835 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.835 g = []
2025-07-02 04:52:33.835 if alo < ahi:
2025-07-02 04:52:33.835 if blo < bhi:
2025-07-02 04:52:33.835 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.835 else:
2025-07-02 04:52:33.835 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.835 elif blo < bhi:
2025-07-02 04:52:33.835 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.836
2025-07-02 04:52:33.836 > yield from g
2025-07-02 04:52:33.836
2025-07-02 04:52:33.836 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.836 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.836
2025-07-02 04:52:33.836 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.836 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.836 alo = 479, ahi = 1101
2025-07-02 04:52:33.836 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.836 blo = 479, bhi = 1101
2025-07-02 04:52:33.836
2025-07-02 04:52:33.836 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.836 r"""
2025-07-02 04:52:33.836 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.836 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.836 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.836 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.836
2025-07-02 04:52:33.836 Example:
2025-07-02 04:52:33.836
2025-07-02 04:52:33.837 >>> d = Differ()
2025-07-02 04:52:33.837 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.837 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.837 >>> print(''.join(results), end="")
2025-07-02 04:52:33.837 - abcDefghiJkl
2025-07-02 04:52:33.837 + abcdefGhijkl
2025-07-02 04:52:33.837 """
2025-07-02 04:52:33.837
2025-07-02 04:52:33.837 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.837 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.837 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.837 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.837 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.837
2025-07-02 04:52:33.837 # search for the pair that matches best without being identical
2025-07-02 04:52:33.837 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.837 # on junk -- unless we have to)
2025-07-02 04:52:33.837 for j in range(blo, bhi):
2025-07-02 04:52:33.838 bj = b[j]
2025-07-02 04:52:33.838 cruncher.set_seq2(bj)
2025-07-02 04:52:33.838 for i in range(alo, ahi):
2025-07-02 04:52:33.838 ai = a[i]
2025-07-02 04:52:33.838 if ai == bj:
2025-07-02 04:52:33.838 if eqi is None:
2025-07-02 04:52:33.838 eqi, eqj = i, j
2025-07-02 04:52:33.838 continue
2025-07-02 04:52:33.838 cruncher.set_seq1(ai)
2025-07-02 04:52:33.838 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.838 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.838 # compares by a factor of 3.
2025-07-02 04:52:33.838 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.838 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.838 # of the computation is cached by cruncher
2025-07-02 04:52:33.838 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.838 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.838 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.838 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.838 if best_ratio < cutoff:
2025-07-02 04:52:33.839 # no non-identical "pretty close" pair
2025-07-02 04:52:33.839 if eqi is None:
2025-07-02 04:52:33.839 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.839 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.839 return
2025-07-02 04:52:33.839 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.839 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.839 else:
2025-07-02 04:52:33.839 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.839 eqi = None
2025-07-02 04:52:33.839
2025-07-02 04:52:33.839 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.839 # identical
2025-07-02 04:52:33.839
2025-07-02 04:52:33.839 # pump out diffs from before the synch point
2025-07-02 04:52:33.839 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.839
2025-07-02 04:52:33.839 # do intraline marking on the synch pair
2025-07-02 04:52:33.839 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.839 if eqi is None:
2025-07-02 04:52:33.839 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.840 atags = btags = ""
2025-07-02 04:52:33.840 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.840 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.840 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.840 if tag == 'replace':
2025-07-02 04:52:33.840 atags += '^' * la
2025-07-02 04:52:33.840 btags += '^' * lb
2025-07-02 04:52:33.840 elif tag == 'delete':
2025-07-02 04:52:33.840 atags += '-' * la
2025-07-02 04:52:33.840 elif tag == 'insert':
2025-07-02 04:52:33.840 btags += '+' * lb
2025-07-02 04:52:33.840 elif tag == 'equal':
2025-07-02 04:52:33.840 atags += ' ' * la
2025-07-02 04:52:33.840 btags += ' ' * lb
2025-07-02 04:52:33.840 else:
2025-07-02 04:52:33.840 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.840 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.840 else:
2025-07-02 04:52:33.840 # the synch pair is identical
2025-07-02 04:52:33.841 yield ' ' + aelt
2025-07-02 04:52:33.841
2025-07-02 04:52:33.841 # pump out diffs from after the synch point
2025-07-02 04:52:33.841 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.841
2025-07-02 04:52:33.841 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.841 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.841
2025-07-02 04:52:33.841 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.841 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.841 alo = 480, ahi = 1101
2025-07-02 04:52:33.841 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.841 blo = 480, bhi = 1101
2025-07-02 04:52:33.841
2025-07-02 04:52:33.841 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.841 g = []
2025-07-02 04:52:33.841 if alo < ahi:
2025-07-02 04:52:33.841 if blo < bhi:
2025-07-02 04:52:33.841 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.841 else:
2025-07-02 04:52:33.841 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.842 elif blo < bhi:
2025-07-02 04:52:33.842 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.842
2025-07-02 04:52:33.842 > yield from g
2025-07-02 04:52:33.842
2025-07-02 04:52:33.842 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.842 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.842
2025-07-02 04:52:33.842 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.842 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.842 alo = 480, ahi = 1101
2025-07-02 04:52:33.842 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.842 blo = 480, bhi = 1101
2025-07-02 04:52:33.842
2025-07-02 04:52:33.842 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.842 r"""
2025-07-02 04:52:33.842 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.842 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.842 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.842 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.843
2025-07-02 04:52:33.843 Example:
2025-07-02 04:52:33.843
2025-07-02 04:52:33.843 >>> d = Differ()
2025-07-02 04:52:33.843 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.843 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.843 >>> print(''.join(results), end="")
2025-07-02 04:52:33.843 - abcDefghiJkl
2025-07-02 04:52:33.843 + abcdefGhijkl
2025-07-02 04:52:33.843 """
2025-07-02 04:52:33.843
2025-07-02 04:52:33.843 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.843 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.843 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.843 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.843 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.843
2025-07-02 04:52:33.843 # search for the pair that matches best without being identical
2025-07-02 04:52:33.843 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.844 # on junk -- unless we have to)
2025-07-02 04:52:33.844 for j in range(blo, bhi):
2025-07-02 04:52:33.844 bj = b[j]
2025-07-02 04:52:33.844 cruncher.set_seq2(bj)
2025-07-02 04:52:33.844 for i in range(alo, ahi):
2025-07-02 04:52:33.844 ai = a[i]
2025-07-02 04:52:33.844 if ai == bj:
2025-07-02 04:52:33.844 if eqi is None:
2025-07-02 04:52:33.844 eqi, eqj = i, j
2025-07-02 04:52:33.844 continue
2025-07-02 04:52:33.844 cruncher.set_seq1(ai)
2025-07-02 04:52:33.844 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.844 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.844 # compares by a factor of 3.
2025-07-02 04:52:33.844 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.844 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.844 # of the computation is cached by cruncher
2025-07-02 04:52:33.844 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.844 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.844 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.844 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.845 if best_ratio < cutoff:
2025-07-02 04:52:33.845 # no non-identical "pretty close" pair
2025-07-02 04:52:33.845 if eqi is None:
2025-07-02 04:52:33.845 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.845 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.845 return
2025-07-02 04:52:33.845 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.845 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.845 else:
2025-07-02 04:52:33.845 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.845 eqi = None
2025-07-02 04:52:33.845
2025-07-02 04:52:33.845 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.845 # identical
2025-07-02 04:52:33.845
2025-07-02 04:52:33.845 # pump out diffs from before the synch point
2025-07-02 04:52:33.845 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.845
2025-07-02 04:52:33.845 # do intraline marking on the synch pair
2025-07-02 04:52:33.845 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.845 if eqi is None:
2025-07-02 04:52:33.845 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.846 atags = btags = ""
2025-07-02 04:52:33.846 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.846 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.846 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.846 if tag == 'replace':
2025-07-02 04:52:33.846 atags += '^' * la
2025-07-02 04:52:33.846 btags += '^' * lb
2025-07-02 04:52:33.846 elif tag == 'delete':
2025-07-02 04:52:33.846 atags += '-' * la
2025-07-02 04:52:33.846 elif tag == 'insert':
2025-07-02 04:52:33.846 btags += '+' * lb
2025-07-02 04:52:33.846 elif tag == 'equal':
2025-07-02 04:52:33.846 atags += ' ' * la
2025-07-02 04:52:33.846 btags += ' ' * lb
2025-07-02 04:52:33.846 else:
2025-07-02 04:52:33.846 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.846 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.846 else:
2025-07-02 04:52:33.847 # the synch pair is identical
2025-07-02 04:52:33.847 yield ' ' + aelt
2025-07-02 04:52:33.847
2025-07-02 04:52:33.847 # pump out diffs from after the synch point
2025-07-02 04:52:33.847 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.847
2025-07-02 04:52:33.847 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.847 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.847
2025-07-02 04:52:33.847 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.847 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.847 alo = 481, ahi = 1101
2025-07-02 04:52:33.847 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.847 blo = 481, bhi = 1101
2025-07-02 04:52:33.847
2025-07-02 04:52:33.847 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.847 g = []
2025-07-02 04:52:33.847 if alo < ahi:
2025-07-02 04:52:33.847 if blo < bhi:
2025-07-02 04:52:33.847 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.847 else:
2025-07-02 04:52:33.848 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.848 elif blo < bhi:
2025-07-02 04:52:33.848 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.848
2025-07-02 04:52:33.848 > yield from g
2025-07-02 04:52:33.848
2025-07-02 04:52:33.848 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.848 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.848
2025-07-02 04:52:33.848 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.848 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.848 alo = 481, ahi = 1101
2025-07-02 04:52:33.848 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.848 blo = 481, bhi = 1101
2025-07-02 04:52:33.848
2025-07-02 04:52:33.848 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.848 r"""
2025-07-02 04:52:33.848 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.848 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.848 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.848 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.849
2025-07-02 04:52:33.849 Example:
2025-07-02 04:52:33.849
2025-07-02 04:52:33.849 >>> d = Differ()
2025-07-02 04:52:33.849 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.849 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.849 >>> print(''.join(results), end="")
2025-07-02 04:52:33.849 - abcDefghiJkl
2025-07-02 04:52:33.849 + abcdefGhijkl
2025-07-02 04:52:33.849 """
2025-07-02 04:52:33.849
2025-07-02 04:52:33.849 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.849 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.849 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.849 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.849 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.849
2025-07-02 04:52:33.849 # search for the pair that matches best without being identical
2025-07-02 04:52:33.849 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.850 # on junk -- unless we have to)
2025-07-02 04:52:33.850 for j in range(blo, bhi):
2025-07-02 04:52:33.850 bj = b[j]
2025-07-02 04:52:33.850 cruncher.set_seq2(bj)
2025-07-02 04:52:33.850 for i in range(alo, ahi):
2025-07-02 04:52:33.850 ai = a[i]
2025-07-02 04:52:33.850 if ai == bj:
2025-07-02 04:52:33.850 if eqi is None:
2025-07-02 04:52:33.850 eqi, eqj = i, j
2025-07-02 04:52:33.850 continue
2025-07-02 04:52:33.850 cruncher.set_seq1(ai)
2025-07-02 04:52:33.850 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.850 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.850 # compares by a factor of 3.
2025-07-02 04:52:33.850 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.850 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.850 # of the computation is cached by cruncher
2025-07-02 04:52:33.850 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.850 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.850 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.850 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.851 if best_ratio < cutoff:
2025-07-02 04:52:33.851 # no non-identical "pretty close" pair
2025-07-02 04:52:33.851 if eqi is None:
2025-07-02 04:52:33.851 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.851 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.851 return
2025-07-02 04:52:33.851 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.851 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.851 else:
2025-07-02 04:52:33.851 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.851 eqi = None
2025-07-02 04:52:33.851
2025-07-02 04:52:33.851 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.851 # identical
2025-07-02 04:52:33.851
2025-07-02 04:52:33.851 # pump out diffs from before the synch point
2025-07-02 04:52:33.851 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.851
2025-07-02 04:52:33.851 # do intraline marking on the synch pair
2025-07-02 04:52:33.851 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.851 if eqi is None:
2025-07-02 04:52:33.851 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.852 atags = btags = ""
2025-07-02 04:52:33.852 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.852 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.852 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.852 if tag == 'replace':
2025-07-02 04:52:33.852 atags += '^' * la
2025-07-02 04:52:33.852 btags += '^' * lb
2025-07-02 04:52:33.852 elif tag == 'delete':
2025-07-02 04:52:33.852 atags += '-' * la
2025-07-02 04:52:33.852 elif tag == 'insert':
2025-07-02 04:52:33.852 btags += '+' * lb
2025-07-02 04:52:33.852 elif tag == 'equal':
2025-07-02 04:52:33.852 atags += ' ' * la
2025-07-02 04:52:33.852 btags += ' ' * lb
2025-07-02 04:52:33.852 else:
2025-07-02 04:52:33.852 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.852 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.852 else:
2025-07-02 04:52:33.852 # the synch pair is identical
2025-07-02 04:52:33.852 yield ' ' + aelt
2025-07-02 04:52:33.853
2025-07-02 04:52:33.853 # pump out diffs from after the synch point
2025-07-02 04:52:33.853 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.853
2025-07-02 04:52:33.853 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.853 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.853
2025-07-02 04:52:33.853 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.853 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.853 alo = 482, ahi = 1101
2025-07-02 04:52:33.853 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.853 blo = 482, bhi = 1101
2025-07-02 04:52:33.853
2025-07-02 04:52:33.853 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.853 g = []
2025-07-02 04:52:33.853 if alo < ahi:
2025-07-02 04:52:33.853 if blo < bhi:
2025-07-02 04:52:33.853 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.853 else:
2025-07-02 04:52:33.853 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.853 elif blo < bhi:
2025-07-02 04:52:33.854 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.854
2025-07-02 04:52:33.854 > yield from g
2025-07-02 04:52:33.854
2025-07-02 04:52:33.854 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.854 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.854
2025-07-02 04:52:33.854 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.854 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.854 alo = 482, ahi = 1101
2025-07-02 04:52:33.854 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.854 blo = 482, bhi = 1101
2025-07-02 04:52:33.854
2025-07-02 04:52:33.854 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.854 r"""
2025-07-02 04:52:33.854 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.854 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.854 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.854 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.855
2025-07-02 04:52:33.855 Example:
2025-07-02 04:52:33.855
2025-07-02 04:52:33.855 >>> d = Differ()
2025-07-02 04:52:33.855 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.855 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.855 >>> print(''.join(results), end="")
2025-07-02 04:52:33.855 - abcDefghiJkl
2025-07-02 04:52:33.855 + abcdefGhijkl
2025-07-02 04:52:33.855 """
2025-07-02 04:52:33.855
2025-07-02 04:52:33.855 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.855 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.855 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.855 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.855 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.855
2025-07-02 04:52:33.855 # search for the pair that matches best without being identical
2025-07-02 04:52:33.855 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.856 # on junk -- unless we have to)
2025-07-02 04:52:33.856 for j in range(blo, bhi):
2025-07-02 04:52:33.856 bj = b[j]
2025-07-02 04:52:33.856 cruncher.set_seq2(bj)
2025-07-02 04:52:33.856 for i in range(alo, ahi):
2025-07-02 04:52:33.856 ai = a[i]
2025-07-02 04:52:33.856 if ai == bj:
2025-07-02 04:52:33.856 if eqi is None:
2025-07-02 04:52:33.856 eqi, eqj = i, j
2025-07-02 04:52:33.856 continue
2025-07-02 04:52:33.856 cruncher.set_seq1(ai)
2025-07-02 04:52:33.856 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.856 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.856 # compares by a factor of 3.
2025-07-02 04:52:33.856 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.856 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.856 # of the computation is cached by cruncher
2025-07-02 04:52:33.856 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.856 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.857 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.857 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.857 if best_ratio < cutoff:
2025-07-02 04:52:33.857 # no non-identical "pretty close" pair
2025-07-02 04:52:33.857 if eqi is None:
2025-07-02 04:52:33.857 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.857 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.857 return
2025-07-02 04:52:33.857 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.857 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.857 else:
2025-07-02 04:52:33.857 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.857 eqi = None
2025-07-02 04:52:33.857
2025-07-02 04:52:33.857 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.857 # identical
2025-07-02 04:52:33.857
2025-07-02 04:52:33.857 # pump out diffs from before the synch point
2025-07-02 04:52:33.857 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.858
2025-07-02 04:52:33.858 # do intraline marking on the synch pair
2025-07-02 04:52:33.858 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.858 if eqi is None:
2025-07-02 04:52:33.858 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.858 atags = btags = ""
2025-07-02 04:52:33.858 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.858 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.858 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.858 if tag == 'replace':
2025-07-02 04:52:33.858 atags += '^' * la
2025-07-02 04:52:33.858 btags += '^' * lb
2025-07-02 04:52:33.858 elif tag == 'delete':
2025-07-02 04:52:33.858 atags += '-' * la
2025-07-02 04:52:33.858 elif tag == 'insert':
2025-07-02 04:52:33.858 btags += '+' * lb
2025-07-02 04:52:33.858 elif tag == 'equal':
2025-07-02 04:52:33.858 atags += ' ' * la
2025-07-02 04:52:33.858 btags += ' ' * lb
2025-07-02 04:52:33.858 else:
2025-07-02 04:52:33.859 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.859 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.859 else:
2025-07-02 04:52:33.859 # the synch pair is identical
2025-07-02 04:52:33.859 yield ' ' + aelt
2025-07-02 04:52:33.859
2025-07-02 04:52:33.859 # pump out diffs from after the synch point
2025-07-02 04:52:33.859 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.859
2025-07-02 04:52:33.859 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.859 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.859
2025-07-02 04:52:33.859 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.859 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.859 alo = 483, ahi = 1101
2025-07-02 04:52:33.859 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.859 blo = 483, bhi = 1101
2025-07-02 04:52:33.859
2025-07-02 04:52:33.859 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.859 g = []
2025-07-02 04:52:33.860 if alo < ahi:
2025-07-02 04:52:33.860 if blo < bhi:
2025-07-02 04:52:33.860 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.860 else:
2025-07-02 04:52:33.860 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.860 elif blo < bhi:
2025-07-02 04:52:33.860 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.860
2025-07-02 04:52:33.860 > yield from g
2025-07-02 04:52:33.860
2025-07-02 04:52:33.860 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.860 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.860
2025-07-02 04:52:33.860 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.860 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.860 alo = 483, ahi = 1101
2025-07-02 04:52:33.860 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.860 blo = 483, bhi = 1101
2025-07-02 04:52:33.860
2025-07-02 04:52:33.861 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.861 r"""
2025-07-02 04:52:33.861 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.861 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.861 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.861 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.861
2025-07-02 04:52:33.861 Example:
2025-07-02 04:52:33.861
2025-07-02 04:52:33.861 >>> d = Differ()
2025-07-02 04:52:33.861 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.861 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.861 >>> print(''.join(results), end="")
2025-07-02 04:52:33.861 - abcDefghiJkl
2025-07-02 04:52:33.861 + abcdefGhijkl
2025-07-02 04:52:33.861 """
2025-07-02 04:52:33.861
2025-07-02 04:52:33.861 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.861 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.862 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.862 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.862 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.862
2025-07-02 04:52:33.862 # search for the pair that matches best without being identical
2025-07-02 04:52:33.862 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.862 # on junk -- unless we have to)
2025-07-02 04:52:33.862 for j in range(blo, bhi):
2025-07-02 04:52:33.862 bj = b[j]
2025-07-02 04:52:33.862 cruncher.set_seq2(bj)
2025-07-02 04:52:33.862 for i in range(alo, ahi):
2025-07-02 04:52:33.862 ai = a[i]
2025-07-02 04:52:33.862 if ai == bj:
2025-07-02 04:52:33.862 if eqi is None:
2025-07-02 04:52:33.862 eqi, eqj = i, j
2025-07-02 04:52:33.862 continue
2025-07-02 04:52:33.862 cruncher.set_seq1(ai)
2025-07-02 04:52:33.862 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.862 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.863 # compares by a factor of 3.
2025-07-02 04:52:33.863 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.863 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.863 # of the computation is cached by cruncher
2025-07-02 04:52:33.863 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.863 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.863 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.863 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.863 if best_ratio < cutoff:
2025-07-02 04:52:33.863 # no non-identical "pretty close" pair
2025-07-02 04:52:33.863 if eqi is None:
2025-07-02 04:52:33.863 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.863 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.863 return
2025-07-02 04:52:33.863 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.863 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.863 else:
2025-07-02 04:52:33.863 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.864 eqi = None
2025-07-02 04:52:33.864
2025-07-02 04:52:33.864 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.864 # identical
2025-07-02 04:52:33.864
2025-07-02 04:52:33.864 # pump out diffs from before the synch point
2025-07-02 04:52:33.864 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.864
2025-07-02 04:52:33.864 # do intraline marking on the synch pair
2025-07-02 04:52:33.864 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.864 if eqi is None:
2025-07-02 04:52:33.864 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.864 atags = btags = ""
2025-07-02 04:52:33.864 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.864 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.864 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.864 if tag == 'replace':
2025-07-02 04:52:33.864 atags += '^' * la
2025-07-02 04:52:33.864 btags += '^' * lb
2025-07-02 04:52:33.864 elif tag == 'delete':
2025-07-02 04:52:33.864 atags += '-' * la
2025-07-02 04:52:33.865 elif tag == 'insert':
2025-07-02 04:52:33.865 btags += '+' * lb
2025-07-02 04:52:33.865 elif tag == 'equal':
2025-07-02 04:52:33.865 atags += ' ' * la
2025-07-02 04:52:33.865 btags += ' ' * lb
2025-07-02 04:52:33.865 else:
2025-07-02 04:52:33.865 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.865 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.865 else:
2025-07-02 04:52:33.865 # the synch pair is identical
2025-07-02 04:52:33.865 yield ' ' + aelt
2025-07-02 04:52:33.865
2025-07-02 04:52:33.865 # pump out diffs from after the synch point
2025-07-02 04:52:33.865 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.865
2025-07-02 04:52:33.865 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.865 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.865
2025-07-02 04:52:33.865 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.865 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.865 alo = 484, ahi = 1101
2025-07-02 04:52:33.865 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.866 blo = 484, bhi = 1101
2025-07-02 04:52:33.866
2025-07-02 04:52:33.866 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.866 g = []
2025-07-02 04:52:33.866 if alo < ahi:
2025-07-02 04:52:33.866 if blo < bhi:
2025-07-02 04:52:33.866 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.866 else:
2025-07-02 04:52:33.866 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.866 elif blo < bhi:
2025-07-02 04:52:33.866 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.866
2025-07-02 04:52:33.866 > yield from g
2025-07-02 04:52:33.866
2025-07-02 04:52:33.866 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.866 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.866
2025-07-02 04:52:33.866 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.866 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.867 alo = 484, ahi = 1101
2025-07-02 04:52:33.867 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.867 blo = 484, bhi = 1101
2025-07-02 04:52:33.867
2025-07-02 04:52:33.867 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.867 r"""
2025-07-02 04:52:33.867 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.867 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.867 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.867 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.867
2025-07-02 04:52:33.867 Example:
2025-07-02 04:52:33.867
2025-07-02 04:52:33.867 >>> d = Differ()
2025-07-02 04:52:33.867 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.867 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.867 >>> print(''.join(results), end="")
2025-07-02 04:52:33.867 - abcDefghiJkl
2025-07-02 04:52:33.867 + abcdefGhijkl
2025-07-02 04:52:33.868 """
2025-07-02 04:52:33.868
2025-07-02 04:52:33.868 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.868 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.868 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.868 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.868 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.868
2025-07-02 04:52:33.868 # search for the pair that matches best without being identical
2025-07-02 04:52:33.868 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.868 # on junk -- unless we have to)
2025-07-02 04:52:33.868 for j in range(blo, bhi):
2025-07-02 04:52:33.868 bj = b[j]
2025-07-02 04:52:33.868 cruncher.set_seq2(bj)
2025-07-02 04:52:33.868 for i in range(alo, ahi):
2025-07-02 04:52:33.868 ai = a[i]
2025-07-02 04:52:33.868 if ai == bj:
2025-07-02 04:52:33.868 if eqi is None:
2025-07-02 04:52:33.868 eqi, eqj = i, j
2025-07-02 04:52:33.868 continue
2025-07-02 04:52:33.869 cruncher.set_seq1(ai)
2025-07-02 04:52:33.869 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.869 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.869 # compares by a factor of 3.
2025-07-02 04:52:33.869 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.869 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.869 # of the computation is cached by cruncher
2025-07-02 04:52:33.869 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.869 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.869 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.869 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.869 if best_ratio < cutoff:
2025-07-02 04:52:33.869 # no non-identical "pretty close" pair
2025-07-02 04:52:33.869 if eqi is None:
2025-07-02 04:52:33.869 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.869 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.869 return
2025-07-02 04:52:33.869 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.869 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.869 else:
2025-07-02 04:52:33.869 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.870 eqi = None
2025-07-02 04:52:33.870
2025-07-02 04:52:33.870 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.870 # identical
2025-07-02 04:52:33.870
2025-07-02 04:52:33.870 # pump out diffs from before the synch point
2025-07-02 04:52:33.870 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.870
2025-07-02 04:52:33.870 # do intraline marking on the synch pair
2025-07-02 04:52:33.870 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.870 if eqi is None:
2025-07-02 04:52:33.870 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.870 atags = btags = ""
2025-07-02 04:52:33.870 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.870 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.870 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.870 if tag == 'replace':
2025-07-02 04:52:33.870 atags += '^' * la
2025-07-02 04:52:33.870 btags += '^' * lb
2025-07-02 04:52:33.870 elif tag == 'delete':
2025-07-02 04:52:33.870 atags += '-' * la
2025-07-02 04:52:33.871 elif tag == 'insert':
2025-07-02 04:52:33.871 btags += '+' * lb
2025-07-02 04:52:33.871 elif tag == 'equal':
2025-07-02 04:52:33.871 atags += ' ' * la
2025-07-02 04:52:33.871 btags += ' ' * lb
2025-07-02 04:52:33.871 else:
2025-07-02 04:52:33.871 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.871 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.871 else:
2025-07-02 04:52:33.871 # the synch pair is identical
2025-07-02 04:52:33.871 yield ' ' + aelt
2025-07-02 04:52:33.871
2025-07-02 04:52:33.871 # pump out diffs from after the synch point
2025-07-02 04:52:33.871 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.871
2025-07-02 04:52:33.871 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.871 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.871
2025-07-02 04:52:33.871 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.872 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.872 alo = 485, ahi = 1101
2025-07-02 04:52:33.872 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.872 blo = 485, bhi = 1101
2025-07-02 04:52:33.872
2025-07-02 04:52:33.872 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.872 g = []
2025-07-02 04:52:33.872 if alo < ahi:
2025-07-02 04:52:33.872 if blo < bhi:
2025-07-02 04:52:33.872 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.872 else:
2025-07-02 04:52:33.872 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.872 elif blo < bhi:
2025-07-02 04:52:33.872 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.872
2025-07-02 04:52:33.872 > yield from g
2025-07-02 04:52:33.872
2025-07-02 04:52:33.872 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.872 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.873
2025-07-02 04:52:33.873 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.873 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.873 alo = 485, ahi = 1101
2025-07-02 04:52:33.873 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.873 blo = 485, bhi = 1101
2025-07-02 04:52:33.873
2025-07-02 04:52:33.873 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.873 r"""
2025-07-02 04:52:33.873 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.873 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.873 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.873 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.873
2025-07-02 04:52:33.873 Example:
2025-07-02 04:52:33.873
2025-07-02 04:52:33.873 >>> d = Differ()
2025-07-02 04:52:33.873 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.873 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.873 >>> print(''.join(results), end="")
2025-07-02 04:52:33.874 - abcDefghiJkl
2025-07-02 04:52:33.874 + abcdefGhijkl
2025-07-02 04:52:33.874 """
2025-07-02 04:52:33.874
2025-07-02 04:52:33.874 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.874 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.874 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.874 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.874 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.874
2025-07-02 04:52:33.874 # search for the pair that matches best without being identical
2025-07-02 04:52:33.874 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.874 # on junk -- unless we have to)
2025-07-02 04:52:33.874 for j in range(blo, bhi):
2025-07-02 04:52:33.874 bj = b[j]
2025-07-02 04:52:33.874 cruncher.set_seq2(bj)
2025-07-02 04:52:33.874 for i in range(alo, ahi):
2025-07-02 04:52:33.874 ai = a[i]
2025-07-02 04:52:33.874 if ai == bj:
2025-07-02 04:52:33.875 if eqi is None:
2025-07-02 04:52:33.875 eqi, eqj = i, j
2025-07-02 04:52:33.875 continue
2025-07-02 04:52:33.875 cruncher.set_seq1(ai)
2025-07-02 04:52:33.875 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.875 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.875 # compares by a factor of 3.
2025-07-02 04:52:33.875 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.875 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.875 # of the computation is cached by cruncher
2025-07-02 04:52:33.875 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.875 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.875 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.875 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.875 if best_ratio < cutoff:
2025-07-02 04:52:33.875 # no non-identical "pretty close" pair
2025-07-02 04:52:33.875 if eqi is None:
2025-07-02 04:52:33.875 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.875 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.875 return
2025-07-02 04:52:33.876 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.876 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.876 else:
2025-07-02 04:52:33.876 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.876 eqi = None
2025-07-02 04:52:33.876
2025-07-02 04:52:33.876 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.876 # identical
2025-07-02 04:52:33.876
2025-07-02 04:52:33.876 # pump out diffs from before the synch point
2025-07-02 04:52:33.876 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.876
2025-07-02 04:52:33.876 # do intraline marking on the synch pair
2025-07-02 04:52:33.876 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.876 if eqi is None:
2025-07-02 04:52:33.876 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.876 atags = btags = ""
2025-07-02 04:52:33.876 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.876 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.876 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.876 if tag == 'replace':
2025-07-02 04:52:33.877 atags += '^' * la
2025-07-02 04:52:33.877 btags += '^' * lb
2025-07-02 04:52:33.877 elif tag == 'delete':
2025-07-02 04:52:33.877 atags += '-' * la
2025-07-02 04:52:33.877 elif tag == 'insert':
2025-07-02 04:52:33.877 btags += '+' * lb
2025-07-02 04:52:33.877 elif tag == 'equal':
2025-07-02 04:52:33.877 atags += ' ' * la
2025-07-02 04:52:33.877 btags += ' ' * lb
2025-07-02 04:52:33.877 else:
2025-07-02 04:52:33.877 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.877 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.877 else:
2025-07-02 04:52:33.877 # the synch pair is identical
2025-07-02 04:52:33.877 yield ' ' + aelt
2025-07-02 04:52:33.877
2025-07-02 04:52:33.877 # pump out diffs from after the synch point
2025-07-02 04:52:33.877 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.877
2025-07-02 04:52:33.877 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.877 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.877
2025-07-02 04:52:33.878 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.878 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.878 alo = 488, ahi = 1101
2025-07-02 04:52:33.878 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.878 blo = 488, bhi = 1101
2025-07-02 04:52:33.878
2025-07-02 04:52:33.878 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.878 g = []
2025-07-02 04:52:33.878 if alo < ahi:
2025-07-02 04:52:33.878 if blo < bhi:
2025-07-02 04:52:33.878 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.878 else:
2025-07-02 04:52:33.878 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.878 elif blo < bhi:
2025-07-02 04:52:33.878 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.878
2025-07-02 04:52:33.878 > yield from g
2025-07-02 04:52:33.878
2025-07-02 04:52:33.878 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.878 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.878
2025-07-02 04:52:33.879 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.879 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.879 alo = 488, ahi = 1101
2025-07-02 04:52:33.879 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.879 blo = 488, bhi = 1101
2025-07-02 04:52:33.879
2025-07-02 04:52:33.879 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.879 r"""
2025-07-02 04:52:33.879 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.879 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.879 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.879 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.879
2025-07-02 04:52:33.879 Example:
2025-07-02 04:52:33.879
2025-07-02 04:52:33.879 >>> d = Differ()
2025-07-02 04:52:33.879 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.879 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.879 >>> print(''.join(results), end="")
2025-07-02 04:52:33.879 - abcDefghiJkl
2025-07-02 04:52:33.880 + abcdefGhijkl
2025-07-02 04:52:33.880 """
2025-07-02 04:52:33.880
2025-07-02 04:52:33.880 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.880 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.880 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.880 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.880 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.880
2025-07-02 04:52:33.880 # search for the pair that matches best without being identical
2025-07-02 04:52:33.880 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.880 # on junk -- unless we have to)
2025-07-02 04:52:33.880 for j in range(blo, bhi):
2025-07-02 04:52:33.880 bj = b[j]
2025-07-02 04:52:33.880 cruncher.set_seq2(bj)
2025-07-02 04:52:33.880 for i in range(alo, ahi):
2025-07-02 04:52:33.880 ai = a[i]
2025-07-02 04:52:33.880 if ai == bj:
2025-07-02 04:52:33.880 if eqi is None:
2025-07-02 04:52:33.881 eqi, eqj = i, j
2025-07-02 04:52:33.881 continue
2025-07-02 04:52:33.881 cruncher.set_seq1(ai)
2025-07-02 04:52:33.881 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.881 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.881 # compares by a factor of 3.
2025-07-02 04:52:33.881 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.881 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.881 # of the computation is cached by cruncher
2025-07-02 04:52:33.881 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.881 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.881 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.881 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.881 if best_ratio < cutoff:
2025-07-02 04:52:33.881 # no non-identical "pretty close" pair
2025-07-02 04:52:33.881 if eqi is None:
2025-07-02 04:52:33.881 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.881 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.881 return
2025-07-02 04:52:33.881 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.882 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.882 else:
2025-07-02 04:52:33.882 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.882 eqi = None
2025-07-02 04:52:33.882
2025-07-02 04:52:33.882 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.882 # identical
2025-07-02 04:52:33.882
2025-07-02 04:52:33.882 # pump out diffs from before the synch point
2025-07-02 04:52:33.882 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.882
2025-07-02 04:52:33.882 # do intraline marking on the synch pair
2025-07-02 04:52:33.882 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.882 if eqi is None:
2025-07-02 04:52:33.882 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.882 atags = btags = ""
2025-07-02 04:52:33.882 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.882 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.882 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.882 if tag == 'replace':
2025-07-02 04:52:33.882 atags += '^' * la
2025-07-02 04:52:33.882 btags += '^' * lb
2025-07-02 04:52:33.883 elif tag == 'delete':
2025-07-02 04:52:33.883 atags += '-' * la
2025-07-02 04:52:33.883 elif tag == 'insert':
2025-07-02 04:52:33.883 btags += '+' * lb
2025-07-02 04:52:33.883 elif tag == 'equal':
2025-07-02 04:52:33.883 atags += ' ' * la
2025-07-02 04:52:33.883 btags += ' ' * lb
2025-07-02 04:52:33.883 else:
2025-07-02 04:52:33.883 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.883 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.883 else:
2025-07-02 04:52:33.883 # the synch pair is identical
2025-07-02 04:52:33.883 yield ' ' + aelt
2025-07-02 04:52:33.883
2025-07-02 04:52:33.883 # pump out diffs from after the synch point
2025-07-02 04:52:33.883 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.883
2025-07-02 04:52:33.883 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.883 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.883
2025-07-02 04:52:33.883 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.884 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.884 alo = 489, ahi = 1101
2025-07-02 04:52:33.884 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.884 blo = 489, bhi = 1101
2025-07-02 04:52:33.884
2025-07-02 04:52:33.884 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.884 g = []
2025-07-02 04:52:33.884 if alo < ahi:
2025-07-02 04:52:33.884 if blo < bhi:
2025-07-02 04:52:33.884 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.884 else:
2025-07-02 04:52:33.884 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.884 elif blo < bhi:
2025-07-02 04:52:33.884 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.884
2025-07-02 04:52:33.884 > yield from g
2025-07-02 04:52:33.884
2025-07-02 04:52:33.884 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.884 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.884
2025-07-02 04:52:33.884 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.885 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.885 alo = 489, ahi = 1101
2025-07-02 04:52:33.885 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.885 blo = 489, bhi = 1101
2025-07-02 04:52:33.885
2025-07-02 04:52:33.885 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.885 r"""
2025-07-02 04:52:33.885 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.885 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.885 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.885 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.885
2025-07-02 04:52:33.885 Example:
2025-07-02 04:52:33.885
2025-07-02 04:52:33.885 >>> d = Differ()
2025-07-02 04:52:33.885 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.885 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.885 >>> print(''.join(results), end="")
2025-07-02 04:52:33.885 - abcDefghiJkl
2025-07-02 04:52:33.885 + abcdefGhijkl
2025-07-02 04:52:33.886 """
2025-07-02 04:52:33.886
2025-07-02 04:52:33.886 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.886 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.886 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.886 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.886 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.886
2025-07-02 04:52:33.886 # search for the pair that matches best without being identical
2025-07-02 04:52:33.886 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.886 # on junk -- unless we have to)
2025-07-02 04:52:33.886 for j in range(blo, bhi):
2025-07-02 04:52:33.886 bj = b[j]
2025-07-02 04:52:33.886 cruncher.set_seq2(bj)
2025-07-02 04:52:33.886 for i in range(alo, ahi):
2025-07-02 04:52:33.886 ai = a[i]
2025-07-02 04:52:33.886 if ai == bj:
2025-07-02 04:52:33.886 if eqi is None:
2025-07-02 04:52:33.886 eqi, eqj = i, j
2025-07-02 04:52:33.886 continue
2025-07-02 04:52:33.886 cruncher.set_seq1(ai)
2025-07-02 04:52:33.887 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.887 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.887 # compares by a factor of 3.
2025-07-02 04:52:33.887 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.887 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.887 # of the computation is cached by cruncher
2025-07-02 04:52:33.887 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.887 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.887 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.887 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.887 if best_ratio < cutoff:
2025-07-02 04:52:33.887 # no non-identical "pretty close" pair
2025-07-02 04:52:33.887 if eqi is None:
2025-07-02 04:52:33.887 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.887 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.887 return
2025-07-02 04:52:33.887 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.887 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.887 else:
2025-07-02 04:52:33.887 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.888 eqi = None
2025-07-02 04:52:33.888
2025-07-02 04:52:33.888 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.888 # identical
2025-07-02 04:52:33.888
2025-07-02 04:52:33.888 # pump out diffs from before the synch point
2025-07-02 04:52:33.888 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.888
2025-07-02 04:52:33.888 # do intraline marking on the synch pair
2025-07-02 04:52:33.888 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.888 if eqi is None:
2025-07-02 04:52:33.888 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.888 atags = btags = ""
2025-07-02 04:52:33.888 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.888 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.888 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.888 if tag == 'replace':
2025-07-02 04:52:33.888 atags += '^' * la
2025-07-02 04:52:33.888 btags += '^' * lb
2025-07-02 04:52:33.889 elif tag == 'delete':
2025-07-02 04:52:33.889 atags += '-' * la
2025-07-02 04:52:33.889 elif tag == 'insert':
2025-07-02 04:52:33.889 btags += '+' * lb
2025-07-02 04:52:33.889 elif tag == 'equal':
2025-07-02 04:52:33.889 atags += ' ' * la
2025-07-02 04:52:33.889 btags += ' ' * lb
2025-07-02 04:52:33.889 else:
2025-07-02 04:52:33.889 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.889 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.889 else:
2025-07-02 04:52:33.889 # the synch pair is identical
2025-07-02 04:52:33.889 yield ' ' + aelt
2025-07-02 04:52:33.889
2025-07-02 04:52:33.889 # pump out diffs from after the synch point
2025-07-02 04:52:33.889 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.889
2025-07-02 04:52:33.889 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.889 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.889
2025-07-02 04:52:33.889 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.890 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.890 alo = 490, ahi = 1101
2025-07-02 04:52:33.890 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.890 blo = 490, bhi = 1101
2025-07-02 04:52:33.890
2025-07-02 04:52:33.890 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.890 g = []
2025-07-02 04:52:33.890 if alo < ahi:
2025-07-02 04:52:33.890 if blo < bhi:
2025-07-02 04:52:33.890 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.890 else:
2025-07-02 04:52:33.890 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.890 elif blo < bhi:
2025-07-02 04:52:33.890 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.890
2025-07-02 04:52:33.890 > yield from g
2025-07-02 04:52:33.890
2025-07-02 04:52:33.890 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.890 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.890
2025-07-02 04:52:33.890 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.891 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.891 alo = 490, ahi = 1101
2025-07-02 04:52:33.891 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.891 blo = 490, bhi = 1101
2025-07-02 04:52:33.891
2025-07-02 04:52:33.891 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.891 r"""
2025-07-02 04:52:33.891 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.891 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.891 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.891 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.891
2025-07-02 04:52:33.891 Example:
2025-07-02 04:52:33.891
2025-07-02 04:52:33.891 >>> d = Differ()
2025-07-02 04:52:33.891 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.891 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.891 >>> print(''.join(results), end="")
2025-07-02 04:52:33.891 - abcDefghiJkl
2025-07-02 04:52:33.891 + abcdefGhijkl
2025-07-02 04:52:33.892 """
2025-07-02 04:52:33.892
2025-07-02 04:52:33.892 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.892 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.892 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.892 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.892 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.892
2025-07-02 04:52:33.892 # search for the pair that matches best without being identical
2025-07-02 04:52:33.892 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.892 # on junk -- unless we have to)
2025-07-02 04:52:33.892 for j in range(blo, bhi):
2025-07-02 04:52:33.892 bj = b[j]
2025-07-02 04:52:33.892 cruncher.set_seq2(bj)
2025-07-02 04:52:33.892 for i in range(alo, ahi):
2025-07-02 04:52:33.892 ai = a[i]
2025-07-02 04:52:33.892 if ai == bj:
2025-07-02 04:52:33.892 if eqi is None:
2025-07-02 04:52:33.892 eqi, eqj = i, j
2025-07-02 04:52:33.892 continue
2025-07-02 04:52:33.892 cruncher.set_seq1(ai)
2025-07-02 04:52:33.893 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.893 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.893 # compares by a factor of 3.
2025-07-02 04:52:33.893 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.893 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.893 # of the computation is cached by cruncher
2025-07-02 04:52:33.893 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.893 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.893 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.893 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.893 if best_ratio < cutoff:
2025-07-02 04:52:33.893 # no non-identical "pretty close" pair
2025-07-02 04:52:33.893 if eqi is None:
2025-07-02 04:52:33.893 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.893 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.893 return
2025-07-02 04:52:33.893 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.893 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.893 else:
2025-07-02 04:52:33.893 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.893 eqi = None
2025-07-02 04:52:33.894
2025-07-02 04:52:33.894 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.894 # identical
2025-07-02 04:52:33.894
2025-07-02 04:52:33.894 # pump out diffs from before the synch point
2025-07-02 04:52:33.894 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.894
2025-07-02 04:52:33.894 # do intraline marking on the synch pair
2025-07-02 04:52:33.894 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.894 if eqi is None:
2025-07-02 04:52:33.894 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.894 atags = btags = ""
2025-07-02 04:52:33.894 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.894 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.894 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.894 if tag == 'replace':
2025-07-02 04:52:33.894 atags += '^' * la
2025-07-02 04:52:33.894 btags += '^' * lb
2025-07-02 04:52:33.894 elif tag == 'delete':
2025-07-02 04:52:33.894 atags += '-' * la
2025-07-02 04:52:33.894 elif tag == 'insert':
2025-07-02 04:52:33.895 btags += '+' * lb
2025-07-02 04:52:33.895 elif tag == 'equal':
2025-07-02 04:52:33.895 atags += ' ' * la
2025-07-02 04:52:33.895 btags += ' ' * lb
2025-07-02 04:52:33.895 else:
2025-07-02 04:52:33.895 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.895 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.895 else:
2025-07-02 04:52:33.895 # the synch pair is identical
2025-07-02 04:52:33.895 yield ' ' + aelt
2025-07-02 04:52:33.895
2025-07-02 04:52:33.895 # pump out diffs from after the synch point
2025-07-02 04:52:33.895 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.895
2025-07-02 04:52:33.895 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.895 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.895
2025-07-02 04:52:33.895 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.895 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.895 alo = 491, ahi = 1101
2025-07-02 04:52:33.895 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.896 blo = 491, bhi = 1101
2025-07-02 04:52:33.896
2025-07-02 04:52:33.896 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.896 g = []
2025-07-02 04:52:33.896 if alo < ahi:
2025-07-02 04:52:33.896 if blo < bhi:
2025-07-02 04:52:33.896 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.896 else:
2025-07-02 04:52:33.896 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.896 elif blo < bhi:
2025-07-02 04:52:33.896 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.896
2025-07-02 04:52:33.896 > yield from g
2025-07-02 04:52:33.896
2025-07-02 04:52:33.896 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.896 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.896
2025-07-02 04:52:33.896 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.896 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.897 alo = 491, ahi = 1101
2025-07-02 04:52:33.897 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.897 blo = 491, bhi = 1101
2025-07-02 04:52:33.897
2025-07-02 04:52:33.897 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.897 r"""
2025-07-02 04:52:33.897 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.897 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.897 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.897 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.897
2025-07-02 04:52:33.897 Example:
2025-07-02 04:52:33.897
2025-07-02 04:52:33.897 >>> d = Differ()
2025-07-02 04:52:33.897 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.897 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.897 >>> print(''.join(results), end="")
2025-07-02 04:52:33.897 - abcDefghiJkl
2025-07-02 04:52:33.897 + abcdefGhijkl
2025-07-02 04:52:33.898 """
2025-07-02 04:52:33.898
2025-07-02 04:52:33.898 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.898 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.898 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.898 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.898 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.898
2025-07-02 04:52:33.898 # search for the pair that matches best without being identical
2025-07-02 04:52:33.898 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.898 # on junk -- unless we have to)
2025-07-02 04:52:33.898 for j in range(blo, bhi):
2025-07-02 04:52:33.898 bj = b[j]
2025-07-02 04:52:33.898 cruncher.set_seq2(bj)
2025-07-02 04:52:33.898 for i in range(alo, ahi):
2025-07-02 04:52:33.898 ai = a[i]
2025-07-02 04:52:33.898 if ai == bj:
2025-07-02 04:52:33.898 if eqi is None:
2025-07-02 04:52:33.898 eqi, eqj = i, j
2025-07-02 04:52:33.898 continue
2025-07-02 04:52:33.899 cruncher.set_seq1(ai)
2025-07-02 04:52:33.899 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.899 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.899 # compares by a factor of 3.
2025-07-02 04:52:33.899 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.899 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.899 # of the computation is cached by cruncher
2025-07-02 04:52:33.899 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.899 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.899 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.899 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.899 if best_ratio < cutoff:
2025-07-02 04:52:33.899 # no non-identical "pretty close" pair
2025-07-02 04:52:33.899 if eqi is None:
2025-07-02 04:52:33.899 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.899 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.899 return
2025-07-02 04:52:33.899 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.899 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.899 else:
2025-07-02 04:52:33.899 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.899 eqi = None
2025-07-02 04:52:33.900
2025-07-02 04:52:33.900 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.900 # identical
2025-07-02 04:52:33.900
2025-07-02 04:52:33.900 # pump out diffs from before the synch point
2025-07-02 04:52:33.900 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.900
2025-07-02 04:52:33.900 # do intraline marking on the synch pair
2025-07-02 04:52:33.900 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.900 if eqi is None:
2025-07-02 04:52:33.900 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.900 atags = btags = ""
2025-07-02 04:52:33.900 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.900 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.900 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.900 if tag == 'replace':
2025-07-02 04:52:33.900 atags += '^' * la
2025-07-02 04:52:33.900 btags += '^' * lb
2025-07-02 04:52:33.900 elif tag == 'delete':
2025-07-02 04:52:33.900 atags += '-' * la
2025-07-02 04:52:33.900 elif tag == 'insert':
2025-07-02 04:52:33.901 btags += '+' * lb
2025-07-02 04:52:33.901 elif tag == 'equal':
2025-07-02 04:52:33.901 atags += ' ' * la
2025-07-02 04:52:33.901 btags += ' ' * lb
2025-07-02 04:52:33.901 else:
2025-07-02 04:52:33.901 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.901 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.901 else:
2025-07-02 04:52:33.901 # the synch pair is identical
2025-07-02 04:52:33.901 yield ' ' + aelt
2025-07-02 04:52:33.901
2025-07-02 04:52:33.901 # pump out diffs from after the synch point
2025-07-02 04:52:33.901 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.901
2025-07-02 04:52:33.901 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.901 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.901
2025-07-02 04:52:33.901 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.901 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.901 alo = 492, ahi = 1101
2025-07-02 04:52:33.901 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.902 blo = 492, bhi = 1101
2025-07-02 04:52:33.902
2025-07-02 04:52:33.902 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.902 g = []
2025-07-02 04:52:33.902 if alo < ahi:
2025-07-02 04:52:33.902 if blo < bhi:
2025-07-02 04:52:33.902 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.902 else:
2025-07-02 04:52:33.902 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.902 elif blo < bhi:
2025-07-02 04:52:33.902 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.902
2025-07-02 04:52:33.902 > yield from g
2025-07-02 04:52:33.902
2025-07-02 04:52:33.902 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.902 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.902
2025-07-02 04:52:33.902 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.902 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.902 alo = 492, ahi = 1101
2025-07-02 04:52:33.902 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.903 blo = 492, bhi = 1101
2025-07-02 04:52:33.903
2025-07-02 04:52:33.903 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.903 r"""
2025-07-02 04:52:33.903 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.903 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.903 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.903 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.903
2025-07-02 04:52:33.903 Example:
2025-07-02 04:52:33.903
2025-07-02 04:52:33.903 >>> d = Differ()
2025-07-02 04:52:33.903 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.903 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.903 >>> print(''.join(results), end="")
2025-07-02 04:52:33.903 - abcDefghiJkl
2025-07-02 04:52:33.903 + abcdefGhijkl
2025-07-02 04:52:33.903 """
2025-07-02 04:52:33.903
2025-07-02 04:52:33.903 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.904 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.904 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.904 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.904 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.904
2025-07-02 04:52:33.904 # search for the pair that matches best without being identical
2025-07-02 04:52:33.904 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.904 # on junk -- unless we have to)
2025-07-02 04:52:33.904 for j in range(blo, bhi):
2025-07-02 04:52:33.904 bj = b[j]
2025-07-02 04:52:33.904 cruncher.set_seq2(bj)
2025-07-02 04:52:33.904 for i in range(alo, ahi):
2025-07-02 04:52:33.904 ai = a[i]
2025-07-02 04:52:33.904 if ai == bj:
2025-07-02 04:52:33.904 if eqi is None:
2025-07-02 04:52:33.904 eqi, eqj = i, j
2025-07-02 04:52:33.904 continue
2025-07-02 04:52:33.904 cruncher.set_seq1(ai)
2025-07-02 04:52:33.905 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.905 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.905 # compares by a factor of 3.
2025-07-02 04:52:33.905 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.905 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.905 # of the computation is cached by cruncher
2025-07-02 04:52:33.905 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.905 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.905 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.905 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.905 if best_ratio < cutoff:
2025-07-02 04:52:33.905 # no non-identical "pretty close" pair
2025-07-02 04:52:33.905 if eqi is None:
2025-07-02 04:52:33.905 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.905 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.905 return
2025-07-02 04:52:33.905 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.905 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.905 else:
2025-07-02 04:52:33.905 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.906 eqi = None
2025-07-02 04:52:33.906
2025-07-02 04:52:33.906 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.906 # identical
2025-07-02 04:52:33.906
2025-07-02 04:52:33.906 # pump out diffs from before the synch point
2025-07-02 04:52:33.906 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.906
2025-07-02 04:52:33.906 # do intraline marking on the synch pair
2025-07-02 04:52:33.906 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.906 if eqi is None:
2025-07-02 04:52:33.906 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.906 atags = btags = ""
2025-07-02 04:52:33.906 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.906 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.906 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.906 if tag == 'replace':
2025-07-02 04:52:33.906 atags += '^' * la
2025-07-02 04:52:33.906 btags += '^' * lb
2025-07-02 04:52:33.906 elif tag == 'delete':
2025-07-02 04:52:33.907 atags += '-' * la
2025-07-02 04:52:33.907 elif tag == 'insert':
2025-07-02 04:52:33.907 btags += '+' * lb
2025-07-02 04:52:33.907 elif tag == 'equal':
2025-07-02 04:52:33.907 atags += ' ' * la
2025-07-02 04:52:33.907 btags += ' ' * lb
2025-07-02 04:52:33.907 else:
2025-07-02 04:52:33.907 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.907 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.907 else:
2025-07-02 04:52:33.907 # the synch pair is identical
2025-07-02 04:52:33.907 yield ' ' + aelt
2025-07-02 04:52:33.907
2025-07-02 04:52:33.907 # pump out diffs from after the synch point
2025-07-02 04:52:33.907 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.907
2025-07-02 04:52:33.907 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.907 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.907
2025-07-02 04:52:33.907 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.907 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.908 alo = 493, ahi = 1101
2025-07-02 04:52:33.908 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.908 blo = 493, bhi = 1101
2025-07-02 04:52:33.908
2025-07-02 04:52:33.908 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.908 g = []
2025-07-02 04:52:33.908 if alo < ahi:
2025-07-02 04:52:33.908 if blo < bhi:
2025-07-02 04:52:33.908 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.908 else:
2025-07-02 04:52:33.908 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.908 elif blo < bhi:
2025-07-02 04:52:33.908 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.908
2025-07-02 04:52:33.908 > yield from g
2025-07-02 04:52:33.908
2025-07-02 04:52:33.908 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.908 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.908
2025-07-02 04:52:33.908 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.909 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.909 alo = 493, ahi = 1101
2025-07-02 04:52:33.909 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.909 blo = 493, bhi = 1101
2025-07-02 04:52:33.909
2025-07-02 04:52:33.909 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.909 r"""
2025-07-02 04:52:33.909 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.909 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.909 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.909 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.909
2025-07-02 04:52:33.909 Example:
2025-07-02 04:52:33.909
2025-07-02 04:52:33.909 >>> d = Differ()
2025-07-02 04:52:33.909 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.909 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.909 >>> print(''.join(results), end="")
2025-07-02 04:52:33.909 - abcDefghiJkl
2025-07-02 04:52:33.909 + abcdefGhijkl
2025-07-02 04:52:33.910 """
2025-07-02 04:52:33.910
2025-07-02 04:52:33.910 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.910 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.910 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.910 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.910 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.910
2025-07-02 04:52:33.910 # search for the pair that matches best without being identical
2025-07-02 04:52:33.910 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.910 # on junk -- unless we have to)
2025-07-02 04:52:33.910 for j in range(blo, bhi):
2025-07-02 04:52:33.910 bj = b[j]
2025-07-02 04:52:33.910 cruncher.set_seq2(bj)
2025-07-02 04:52:33.910 for i in range(alo, ahi):
2025-07-02 04:52:33.910 ai = a[i]
2025-07-02 04:52:33.910 if ai == bj:
2025-07-02 04:52:33.910 if eqi is None:
2025-07-02 04:52:33.910 eqi, eqj = i, j
2025-07-02 04:52:33.910 continue
2025-07-02 04:52:33.911 cruncher.set_seq1(ai)
2025-07-02 04:52:33.911 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.911 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.911 # compares by a factor of 3.
2025-07-02 04:52:33.911 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.911 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.911 # of the computation is cached by cruncher
2025-07-02 04:52:33.911 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.911 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.911 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.911 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.911 if best_ratio < cutoff:
2025-07-02 04:52:33.911 # no non-identical "pretty close" pair
2025-07-02 04:52:33.911 if eqi is None:
2025-07-02 04:52:33.911 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.911 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.911 return
2025-07-02 04:52:33.911 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.911 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.911 else:
2025-07-02 04:52:33.911 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.912 eqi = None
2025-07-02 04:52:33.912
2025-07-02 04:52:33.912 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.912 # identical
2025-07-02 04:52:33.912
2025-07-02 04:52:33.912 # pump out diffs from before the synch point
2025-07-02 04:52:33.912 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.912
2025-07-02 04:52:33.912 # do intraline marking on the synch pair
2025-07-02 04:52:33.912 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.912 if eqi is None:
2025-07-02 04:52:33.912 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.912 atags = btags = ""
2025-07-02 04:52:33.912 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.912 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.912 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.912 if tag == 'replace':
2025-07-02 04:52:33.912 atags += '^' * la
2025-07-02 04:52:33.912 btags += '^' * lb
2025-07-02 04:52:33.912 elif tag == 'delete':
2025-07-02 04:52:33.912 atags += '-' * la
2025-07-02 04:52:33.912 elif tag == 'insert':
2025-07-02 04:52:33.913 btags += '+' * lb
2025-07-02 04:52:33.913 elif tag == 'equal':
2025-07-02 04:52:33.913 atags += ' ' * la
2025-07-02 04:52:33.913 btags += ' ' * lb
2025-07-02 04:52:33.913 else:
2025-07-02 04:52:33.913 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.913 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.913 else:
2025-07-02 04:52:33.913 # the synch pair is identical
2025-07-02 04:52:33.913 yield ' ' + aelt
2025-07-02 04:52:33.913
2025-07-02 04:52:33.913 # pump out diffs from after the synch point
2025-07-02 04:52:33.913 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.913
2025-07-02 04:52:33.913 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.913 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.913
2025-07-02 04:52:33.913 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.913 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.914 alo = 494, ahi = 1101
2025-07-02 04:52:33.914 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.914 blo = 494, bhi = 1101
2025-07-02 04:52:33.914
2025-07-02 04:52:33.914 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.914 g = []
2025-07-02 04:52:33.914 if alo < ahi:
2025-07-02 04:52:33.914 if blo < bhi:
2025-07-02 04:52:33.914 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.914 else:
2025-07-02 04:52:33.914 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.914 elif blo < bhi:
2025-07-02 04:52:33.914 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.914
2025-07-02 04:52:33.914 > yield from g
2025-07-02 04:52:33.914
2025-07-02 04:52:33.914 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.914 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.914
2025-07-02 04:52:33.914 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.915 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.915 alo = 494, ahi = 1101
2025-07-02 04:52:33.915 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.915 blo = 494, bhi = 1101
2025-07-02 04:52:33.915
2025-07-02 04:52:33.915 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.915 r"""
2025-07-02 04:52:33.915 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.915 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.915 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.915 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.915
2025-07-02 04:52:33.915 Example:
2025-07-02 04:52:33.915
2025-07-02 04:52:33.915 >>> d = Differ()
2025-07-02 04:52:33.915 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.915 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.915 >>> print(''.join(results), end="")
2025-07-02 04:52:33.915 - abcDefghiJkl
2025-07-02 04:52:33.915 + abcdefGhijkl
2025-07-02 04:52:33.916 """
2025-07-02 04:52:33.916
2025-07-02 04:52:33.916 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.916 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.916 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.916 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.916 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.916
2025-07-02 04:52:33.916 # search for the pair that matches best without being identical
2025-07-02 04:52:33.916 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.916 # on junk -- unless we have to)
2025-07-02 04:52:33.916 for j in range(blo, bhi):
2025-07-02 04:52:33.916 bj = b[j]
2025-07-02 04:52:33.916 cruncher.set_seq2(bj)
2025-07-02 04:52:33.916 for i in range(alo, ahi):
2025-07-02 04:52:33.916 ai = a[i]
2025-07-02 04:52:33.916 if ai == bj:
2025-07-02 04:52:33.916 if eqi is None:
2025-07-02 04:52:33.916 eqi, eqj = i, j
2025-07-02 04:52:33.917 continue
2025-07-02 04:52:33.917 cruncher.set_seq1(ai)
2025-07-02 04:52:33.917 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.917 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.917 # compares by a factor of 3.
2025-07-02 04:52:33.917 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.917 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.917 # of the computation is cached by cruncher
2025-07-02 04:52:33.917 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.917 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.917 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.917 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.917 if best_ratio < cutoff:
2025-07-02 04:52:33.917 # no non-identical "pretty close" pair
2025-07-02 04:52:33.917 if eqi is None:
2025-07-02 04:52:33.917 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.917 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.917 return
2025-07-02 04:52:33.917 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.917 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.917 else:
2025-07-02 04:52:33.917 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.918 eqi = None
2025-07-02 04:52:33.918
2025-07-02 04:52:33.918 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.918 # identical
2025-07-02 04:52:33.918
2025-07-02 04:52:33.918 # pump out diffs from before the synch point
2025-07-02 04:52:33.918 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.918
2025-07-02 04:52:33.918 # do intraline marking on the synch pair
2025-07-02 04:52:33.918 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.918 if eqi is None:
2025-07-02 04:52:33.918 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.918 atags = btags = ""
2025-07-02 04:52:33.918 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.918 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.918 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.918 if tag == 'replace':
2025-07-02 04:52:33.918 atags += '^' * la
2025-07-02 04:52:33.918 btags += '^' * lb
2025-07-02 04:52:33.918 elif tag == 'delete':
2025-07-02 04:52:33.918 atags += '-' * la
2025-07-02 04:52:33.919 elif tag == 'insert':
2025-07-02 04:52:33.919 btags += '+' * lb
2025-07-02 04:52:33.919 elif tag == 'equal':
2025-07-02 04:52:33.919 atags += ' ' * la
2025-07-02 04:52:33.919 btags += ' ' * lb
2025-07-02 04:52:33.919 else:
2025-07-02 04:52:33.919 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.919 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.919 else:
2025-07-02 04:52:33.919 # the synch pair is identical
2025-07-02 04:52:33.919 yield ' ' + aelt
2025-07-02 04:52:33.919
2025-07-02 04:52:33.919 # pump out diffs from after the synch point
2025-07-02 04:52:33.919 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.919
2025-07-02 04:52:33.919 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.919 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.919
2025-07-02 04:52:33.919 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.919 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.919 alo = 495, ahi = 1101
2025-07-02 04:52:33.920 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.920 blo = 495, bhi = 1101
2025-07-02 04:52:33.920
2025-07-02 04:52:33.920 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.920 g = []
2025-07-02 04:52:33.920 if alo < ahi:
2025-07-02 04:52:33.920 if blo < bhi:
2025-07-02 04:52:33.920 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.920 else:
2025-07-02 04:52:33.920 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.920 elif blo < bhi:
2025-07-02 04:52:33.920 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.920
2025-07-02 04:52:33.920 > yield from g
2025-07-02 04:52:33.920
2025-07-02 04:52:33.920 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.920 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.920
2025-07-02 04:52:33.920 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.921 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.921 alo = 495, ahi = 1101
2025-07-02 04:52:33.921 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.921 blo = 495, bhi = 1101
2025-07-02 04:52:33.921
2025-07-02 04:52:33.921 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.921 r"""
2025-07-02 04:52:33.921 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.921 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.921 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.921 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.921
2025-07-02 04:52:33.921 Example:
2025-07-02 04:52:33.921
2025-07-02 04:52:33.921 >>> d = Differ()
2025-07-02 04:52:33.921 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.921 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.921 >>> print(''.join(results), end="")
2025-07-02 04:52:33.921 - abcDefghiJkl
2025-07-02 04:52:33.922 + abcdefGhijkl
2025-07-02 04:52:33.922 """
2025-07-02 04:52:33.922
2025-07-02 04:52:33.922 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.922 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.922 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.922 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.922 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.922
2025-07-02 04:52:33.922 # search for the pair that matches best without being identical
2025-07-02 04:52:33.922 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.922 # on junk -- unless we have to)
2025-07-02 04:52:33.922 for j in range(blo, bhi):
2025-07-02 04:52:33.922 bj = b[j]
2025-07-02 04:52:33.922 cruncher.set_seq2(bj)
2025-07-02 04:52:33.922 for i in range(alo, ahi):
2025-07-02 04:52:33.922 ai = a[i]
2025-07-02 04:52:33.923 if ai == bj:
2025-07-02 04:52:33.923 if eqi is None:
2025-07-02 04:52:33.923 eqi, eqj = i, j
2025-07-02 04:52:33.923 continue
2025-07-02 04:52:33.923 cruncher.set_seq1(ai)
2025-07-02 04:52:33.923 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.923 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.923 # compares by a factor of 3.
2025-07-02 04:52:33.923 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.923 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.923 # of the computation is cached by cruncher
2025-07-02 04:52:33.923 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.923 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.923 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.923 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.923 if best_ratio < cutoff:
2025-07-02 04:52:33.923 # no non-identical "pretty close" pair
2025-07-02 04:52:33.923 if eqi is None:
2025-07-02 04:52:33.923 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.923 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.923 return
2025-07-02 04:52:33.924 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.924 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.924 else:
2025-07-02 04:52:33.924 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.924 eqi = None
2025-07-02 04:52:33.924
2025-07-02 04:52:33.924 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.924 # identical
2025-07-02 04:52:33.924
2025-07-02 04:52:33.924 # pump out diffs from before the synch point
2025-07-02 04:52:33.924 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.924
2025-07-02 04:52:33.924 # do intraline marking on the synch pair
2025-07-02 04:52:33.924 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.924 if eqi is None:
2025-07-02 04:52:33.924 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.924 atags = btags = ""
2025-07-02 04:52:33.924 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.924 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.924 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.924 if tag == 'replace':
2025-07-02 04:52:33.925 atags += '^' * la
2025-07-02 04:52:33.925 btags += '^' * lb
2025-07-02 04:52:33.925 elif tag == 'delete':
2025-07-02 04:52:33.925 atags += '-' * la
2025-07-02 04:52:33.925 elif tag == 'insert':
2025-07-02 04:52:33.925 btags += '+' * lb
2025-07-02 04:52:33.925 elif tag == 'equal':
2025-07-02 04:52:33.925 atags += ' ' * la
2025-07-02 04:52:33.925 btags += ' ' * lb
2025-07-02 04:52:33.925 else:
2025-07-02 04:52:33.925 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.925 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.925 else:
2025-07-02 04:52:33.925 # the synch pair is identical
2025-07-02 04:52:33.925 yield ' ' + aelt
2025-07-02 04:52:33.925
2025-07-02 04:52:33.925 # pump out diffs from after the synch point
2025-07-02 04:52:33.925 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.925
2025-07-02 04:52:33.925 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.925 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.925
2025-07-02 04:52:33.926 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.926 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.926 alo = 496, ahi = 1101
2025-07-02 04:52:33.926 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.926 blo = 496, bhi = 1101
2025-07-02 04:52:33.926
2025-07-02 04:52:33.926 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.926 g = []
2025-07-02 04:52:33.926 if alo < ahi:
2025-07-02 04:52:33.926 if blo < bhi:
2025-07-02 04:52:33.926 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.926 else:
2025-07-02 04:52:33.926 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.926 elif blo < bhi:
2025-07-02 04:52:33.926 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.926
2025-07-02 04:52:33.926 > yield from g
2025-07-02 04:52:33.926
2025-07-02 04:52:33.926 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.926 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.926
2025-07-02 04:52:33.927 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.927 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.927 alo = 496, ahi = 1101
2025-07-02 04:52:33.927 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.927 blo = 496, bhi = 1101
2025-07-02 04:52:33.927
2025-07-02 04:52:33.927 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.927 r"""
2025-07-02 04:52:33.927 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.927 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.927 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.927 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.927
2025-07-02 04:52:33.927 Example:
2025-07-02 04:52:33.927
2025-07-02 04:52:33.927 >>> d = Differ()
2025-07-02 04:52:33.927 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.927 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.927 >>> print(''.join(results), end="")
2025-07-02 04:52:33.927 - abcDefghiJkl
2025-07-02 04:52:33.928 + abcdefGhijkl
2025-07-02 04:52:33.928 """
2025-07-02 04:52:33.928
2025-07-02 04:52:33.928 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.928 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.928 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.928 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.928 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.928
2025-07-02 04:52:33.928 # search for the pair that matches best without being identical
2025-07-02 04:52:33.928 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.928 # on junk -- unless we have to)
2025-07-02 04:52:33.928 for j in range(blo, bhi):
2025-07-02 04:52:33.928 bj = b[j]
2025-07-02 04:52:33.928 cruncher.set_seq2(bj)
2025-07-02 04:52:33.928 for i in range(alo, ahi):
2025-07-02 04:52:33.928 ai = a[i]
2025-07-02 04:52:33.928 if ai == bj:
2025-07-02 04:52:33.928 if eqi is None:
2025-07-02 04:52:33.928 eqi, eqj = i, j
2025-07-02 04:52:33.928 continue
2025-07-02 04:52:33.929 cruncher.set_seq1(ai)
2025-07-02 04:52:33.929 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.929 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.929 # compares by a factor of 3.
2025-07-02 04:52:33.929 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.929 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.929 # of the computation is cached by cruncher
2025-07-02 04:52:33.929 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.929 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.929 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.929 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.929 if best_ratio < cutoff:
2025-07-02 04:52:33.929 # no non-identical "pretty close" pair
2025-07-02 04:52:33.929 if eqi is None:
2025-07-02 04:52:33.929 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.929 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.929 return
2025-07-02 04:52:33.929 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.929 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.929 else:
2025-07-02 04:52:33.930 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.930 eqi = None
2025-07-02 04:52:33.930
2025-07-02 04:52:33.930 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.930 # identical
2025-07-02 04:52:33.930
2025-07-02 04:52:33.930 # pump out diffs from before the synch point
2025-07-02 04:52:33.930 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.930
2025-07-02 04:52:33.930 # do intraline marking on the synch pair
2025-07-02 04:52:33.930 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.930 if eqi is None:
2025-07-02 04:52:33.930 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.930 atags = btags = ""
2025-07-02 04:52:33.930 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.930 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.930 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.930 if tag == 'replace':
2025-07-02 04:52:33.930 atags += '^' * la
2025-07-02 04:52:33.930 btags += '^' * lb
2025-07-02 04:52:33.931 elif tag == 'delete':
2025-07-02 04:52:33.931 atags += '-' * la
2025-07-02 04:52:33.931 elif tag == 'insert':
2025-07-02 04:52:33.931 btags += '+' * lb
2025-07-02 04:52:33.931 elif tag == 'equal':
2025-07-02 04:52:33.931 atags += ' ' * la
2025-07-02 04:52:33.931 btags += ' ' * lb
2025-07-02 04:52:33.931 else:
2025-07-02 04:52:33.931 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.931 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.931 else:
2025-07-02 04:52:33.931 # the synch pair is identical
2025-07-02 04:52:33.931 yield ' ' + aelt
2025-07-02 04:52:33.931
2025-07-02 04:52:33.931 # pump out diffs from after the synch point
2025-07-02 04:52:33.931 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.931
2025-07-02 04:52:33.931 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.931 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.931
2025-07-02 04:52:33.931 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.932 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.932 alo = 497, ahi = 1101
2025-07-02 04:52:33.932 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.932 blo = 497, bhi = 1101
2025-07-02 04:52:33.932
2025-07-02 04:52:33.932 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.932 g = []
2025-07-02 04:52:33.932 if alo < ahi:
2025-07-02 04:52:33.932 if blo < bhi:
2025-07-02 04:52:33.932 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.932 else:
2025-07-02 04:52:33.932 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.932 elif blo < bhi:
2025-07-02 04:52:33.932 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.932
2025-07-02 04:52:33.932 > yield from g
2025-07-02 04:52:33.932
2025-07-02 04:52:33.932 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.932 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.932
2025-07-02 04:52:33.932 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.932 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.933 alo = 497, ahi = 1101
2025-07-02 04:52:33.933 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.933 blo = 497, bhi = 1101
2025-07-02 04:52:33.933
2025-07-02 04:52:33.933 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.933 r"""
2025-07-02 04:52:33.933 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.933 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.933 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.933 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.933
2025-07-02 04:52:33.933 Example:
2025-07-02 04:52:33.933
2025-07-02 04:52:33.933 >>> d = Differ()
2025-07-02 04:52:33.933 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.933 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.933 >>> print(''.join(results), end="")
2025-07-02 04:52:33.933 - abcDefghiJkl
2025-07-02 04:52:33.933 + abcdefGhijkl
2025-07-02 04:52:33.934 """
2025-07-02 04:52:33.934
2025-07-02 04:52:33.934 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.934 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.934 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.934 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.934 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.934
2025-07-02 04:52:33.934 # search for the pair that matches best without being identical
2025-07-02 04:52:33.934 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.934 # on junk -- unless we have to)
2025-07-02 04:52:33.934 for j in range(blo, bhi):
2025-07-02 04:52:33.934 bj = b[j]
2025-07-02 04:52:33.934 cruncher.set_seq2(bj)
2025-07-02 04:52:33.934 for i in range(alo, ahi):
2025-07-02 04:52:33.934 ai = a[i]
2025-07-02 04:52:33.934 if ai == bj:
2025-07-02 04:52:33.934 if eqi is None:
2025-07-02 04:52:33.934 eqi, eqj = i, j
2025-07-02 04:52:33.934 continue
2025-07-02 04:52:33.934 cruncher.set_seq1(ai)
2025-07-02 04:52:33.934 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.935 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.935 # compares by a factor of 3.
2025-07-02 04:52:33.935 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.935 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.935 # of the computation is cached by cruncher
2025-07-02 04:52:33.935 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.935 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.935 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.935 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.935 if best_ratio < cutoff:
2025-07-02 04:52:33.935 # no non-identical "pretty close" pair
2025-07-02 04:52:33.935 if eqi is None:
2025-07-02 04:52:33.935 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.935 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.935 return
2025-07-02 04:52:33.935 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.935 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.935 else:
2025-07-02 04:52:33.935 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.935 eqi = None
2025-07-02 04:52:33.935
2025-07-02 04:52:33.936 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.936 # identical
2025-07-02 04:52:33.936
2025-07-02 04:52:33.936 # pump out diffs from before the synch point
2025-07-02 04:52:33.936 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.936
2025-07-02 04:52:33.936 # do intraline marking on the synch pair
2025-07-02 04:52:33.936 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.936 if eqi is None:
2025-07-02 04:52:33.936 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.936 atags = btags = ""
2025-07-02 04:52:33.936 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.936 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.936 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.936 if tag == 'replace':
2025-07-02 04:52:33.936 atags += '^' * la
2025-07-02 04:52:33.936 btags += '^' * lb
2025-07-02 04:52:33.936 elif tag == 'delete':
2025-07-02 04:52:33.937 atags += '-' * la
2025-07-02 04:52:33.937 elif tag == 'insert':
2025-07-02 04:52:33.937 btags += '+' * lb
2025-07-02 04:52:33.937 elif tag == 'equal':
2025-07-02 04:52:33.937 atags += ' ' * la
2025-07-02 04:52:33.937 btags += ' ' * lb
2025-07-02 04:52:33.937 else:
2025-07-02 04:52:33.937 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.937 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.937 else:
2025-07-02 04:52:33.937 # the synch pair is identical
2025-07-02 04:52:33.937 yield ' ' + aelt
2025-07-02 04:52:33.937
2025-07-02 04:52:33.937 # pump out diffs from after the synch point
2025-07-02 04:52:33.937 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.937
2025-07-02 04:52:33.937 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.937 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.937
2025-07-02 04:52:33.937 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.937 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.937 alo = 498, ahi = 1101
2025-07-02 04:52:33.937 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.937 blo = 498, bhi = 1101
2025-07-02 04:52:33.938
2025-07-02 04:52:33.938 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.938 g = []
2025-07-02 04:52:33.938 if alo < ahi:
2025-07-02 04:52:33.938 if blo < bhi:
2025-07-02 04:52:33.938 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.938 else:
2025-07-02 04:52:33.938 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.938 elif blo < bhi:
2025-07-02 04:52:33.938 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.938
2025-07-02 04:52:33.938 > yield from g
2025-07-02 04:52:33.938
2025-07-02 04:52:33.938 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.938 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.938
2025-07-02 04:52:33.938 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.938 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.938 alo = 498, ahi = 1101
2025-07-02 04:52:33.938 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.938 blo = 498, bhi = 1101
2025-07-02 04:52:33.939
2025-07-02 04:52:33.939 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.939 r"""
2025-07-02 04:52:33.939 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.939 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.939 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.939 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.939
2025-07-02 04:52:33.939 Example:
2025-07-02 04:52:33.939
2025-07-02 04:52:33.939 >>> d = Differ()
2025-07-02 04:52:33.939 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.939 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.939 >>> print(''.join(results), end="")
2025-07-02 04:52:33.939 - abcDefghiJkl
2025-07-02 04:52:33.939 + abcdefGhijkl
2025-07-02 04:52:33.939 """
2025-07-02 04:52:33.939
2025-07-02 04:52:33.939 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.940 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.940 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.940 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.940 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.940
2025-07-02 04:52:33.940 # search for the pair that matches best without being identical
2025-07-02 04:52:33.940 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.940 # on junk -- unless we have to)
2025-07-02 04:52:33.940 for j in range(blo, bhi):
2025-07-02 04:52:33.940 bj = b[j]
2025-07-02 04:52:33.940 cruncher.set_seq2(bj)
2025-07-02 04:52:33.940 for i in range(alo, ahi):
2025-07-02 04:52:33.940 ai = a[i]
2025-07-02 04:52:33.940 if ai == bj:
2025-07-02 04:52:33.940 if eqi is None:
2025-07-02 04:52:33.940 eqi, eqj = i, j
2025-07-02 04:52:33.940 continue
2025-07-02 04:52:33.940 cruncher.set_seq1(ai)
2025-07-02 04:52:33.940 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.940 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.940 # compares by a factor of 3.
2025-07-02 04:52:33.941 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.941 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.941 # of the computation is cached by cruncher
2025-07-02 04:52:33.941 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.941 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.941 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.941 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.941 if best_ratio < cutoff:
2025-07-02 04:52:33.941 # no non-identical "pretty close" pair
2025-07-02 04:52:33.941 if eqi is None:
2025-07-02 04:52:33.941 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.941 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.941 return
2025-07-02 04:52:33.941 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.941 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.941 else:
2025-07-02 04:52:33.941 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.941 eqi = None
2025-07-02 04:52:33.941
2025-07-02 04:52:33.941 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.941 # identical
2025-07-02 04:52:33.942
2025-07-02 04:52:33.942 # pump out diffs from before the synch point
2025-07-02 04:52:33.942 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.942
2025-07-02 04:52:33.942 # do intraline marking on the synch pair
2025-07-02 04:52:33.942 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.942 if eqi is None:
2025-07-02 04:52:33.942 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.942 atags = btags = ""
2025-07-02 04:52:33.942 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.942 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.942 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.942 if tag == 'replace':
2025-07-02 04:52:33.942 atags += '^' * la
2025-07-02 04:52:33.942 btags += '^' * lb
2025-07-02 04:52:33.942 elif tag == 'delete':
2025-07-02 04:52:33.942 atags += '-' * la
2025-07-02 04:52:33.942 elif tag == 'insert':
2025-07-02 04:52:33.942 btags += '+' * lb
2025-07-02 04:52:33.942 elif tag == 'equal':
2025-07-02 04:52:33.942 atags += ' ' * la
2025-07-02 04:52:33.943 btags += ' ' * lb
2025-07-02 04:52:33.943 else:
2025-07-02 04:52:33.943 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.943 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.943 else:
2025-07-02 04:52:33.943 # the synch pair is identical
2025-07-02 04:52:33.943 yield ' ' + aelt
2025-07-02 04:52:33.943
2025-07-02 04:52:33.943 # pump out diffs from after the synch point
2025-07-02 04:52:33.943 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.943
2025-07-02 04:52:33.943 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.943 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.943
2025-07-02 04:52:33.943 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.943 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.943 alo = 499, ahi = 1101
2025-07-02 04:52:33.943 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.943 blo = 499, bhi = 1101
2025-07-02 04:52:33.943
2025-07-02 04:52:33.943 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.944 g = []
2025-07-02 04:52:33.944 if alo < ahi:
2025-07-02 04:52:33.944 if blo < bhi:
2025-07-02 04:52:33.944 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.944 else:
2025-07-02 04:52:33.944 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.944 elif blo < bhi:
2025-07-02 04:52:33.944 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.944
2025-07-02 04:52:33.944 > yield from g
2025-07-02 04:52:33.944
2025-07-02 04:52:33.944 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.944 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.944
2025-07-02 04:52:33.944 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.944 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.944 alo = 499, ahi = 1101
2025-07-02 04:52:33.944 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.944 blo = 499, bhi = 1101
2025-07-02 04:52:33.945
2025-07-02 04:52:33.945 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.945 r"""
2025-07-02 04:52:33.945 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.945 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.945 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.945 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.945
2025-07-02 04:52:33.945 Example:
2025-07-02 04:52:33.945
2025-07-02 04:52:33.945 >>> d = Differ()
2025-07-02 04:52:33.945 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.945 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.945 >>> print(''.join(results), end="")
2025-07-02 04:52:33.945 - abcDefghiJkl
2025-07-02 04:52:33.945 + abcdefGhijkl
2025-07-02 04:52:33.945 """
2025-07-02 04:52:33.945
2025-07-02 04:52:33.945 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.946 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.946 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.946 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.946 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.946
2025-07-02 04:52:33.946 # search for the pair that matches best without being identical
2025-07-02 04:52:33.946 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.946 # on junk -- unless we have to)
2025-07-02 04:52:33.946 for j in range(blo, bhi):
2025-07-02 04:52:33.946 bj = b[j]
2025-07-02 04:52:33.946 cruncher.set_seq2(bj)
2025-07-02 04:52:33.946 for i in range(alo, ahi):
2025-07-02 04:52:33.946 ai = a[i]
2025-07-02 04:52:33.946 if ai == bj:
2025-07-02 04:52:33.946 if eqi is None:
2025-07-02 04:52:33.946 eqi, eqj = i, j
2025-07-02 04:52:33.946 continue
2025-07-02 04:52:33.946 cruncher.set_seq1(ai)
2025-07-02 04:52:33.946 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.947 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.947 # compares by a factor of 3.
2025-07-02 04:52:33.947 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.947 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.947 # of the computation is cached by cruncher
2025-07-02 04:52:33.947 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.947 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.947 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.947 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.947 if best_ratio < cutoff:
2025-07-02 04:52:33.947 # no non-identical "pretty close" pair
2025-07-02 04:52:33.947 if eqi is None:
2025-07-02 04:52:33.947 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.947 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.947 return
2025-07-02 04:52:33.947 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.947 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.947 else:
2025-07-02 04:52:33.947 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.947 eqi = None
2025-07-02 04:52:33.947
2025-07-02 04:52:33.948 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.948 # identical
2025-07-02 04:52:33.948
2025-07-02 04:52:33.948 # pump out diffs from before the synch point
2025-07-02 04:52:33.948 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.948
2025-07-02 04:52:33.948 # do intraline marking on the synch pair
2025-07-02 04:52:33.948 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.948 if eqi is None:
2025-07-02 04:52:33.948 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.948 atags = btags = ""
2025-07-02 04:52:33.948 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.948 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.948 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.948 if tag == 'replace':
2025-07-02 04:52:33.948 atags += '^' * la
2025-07-02 04:52:33.948 btags += '^' * lb
2025-07-02 04:52:33.948 elif tag == 'delete':
2025-07-02 04:52:33.948 atags += '-' * la
2025-07-02 04:52:33.948 elif tag == 'insert':
2025-07-02 04:52:33.948 btags += '+' * lb
2025-07-02 04:52:33.949 elif tag == 'equal':
2025-07-02 04:52:33.949 atags += ' ' * la
2025-07-02 04:52:33.949 btags += ' ' * lb
2025-07-02 04:52:33.949 else:
2025-07-02 04:52:33.949 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.949 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.949 else:
2025-07-02 04:52:33.949 # the synch pair is identical
2025-07-02 04:52:33.949 yield ' ' + aelt
2025-07-02 04:52:33.949
2025-07-02 04:52:33.949 # pump out diffs from after the synch point
2025-07-02 04:52:33.949 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.949
2025-07-02 04:52:33.949 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.949 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.949
2025-07-02 04:52:33.949 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.949 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.949 alo = 500, ahi = 1101
2025-07-02 04:52:33.949 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.950 blo = 500, bhi = 1101
2025-07-02 04:52:33.950
2025-07-02 04:52:33.950 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.950 g = []
2025-07-02 04:52:33.950 if alo < ahi:
2025-07-02 04:52:33.950 if blo < bhi:
2025-07-02 04:52:33.950 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.950 else:
2025-07-02 04:52:33.950 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.950 elif blo < bhi:
2025-07-02 04:52:33.950 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.950
2025-07-02 04:52:33.950 > yield from g
2025-07-02 04:52:33.950
2025-07-02 04:52:33.950 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.950 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.950
2025-07-02 04:52:33.950 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.950 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.950 alo = 500, ahi = 1101
2025-07-02 04:52:33.950 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.951 blo = 500, bhi = 1101
2025-07-02 04:52:33.951
2025-07-02 04:52:33.951 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.951 r"""
2025-07-02 04:52:33.951 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.951 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.951 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.951 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.951
2025-07-02 04:52:33.951 Example:
2025-07-02 04:52:33.951
2025-07-02 04:52:33.951 >>> d = Differ()
2025-07-02 04:52:33.951 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.951 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.951 >>> print(''.join(results), end="")
2025-07-02 04:52:33.951 - abcDefghiJkl
2025-07-02 04:52:33.951 + abcdefGhijkl
2025-07-02 04:52:33.952 """
2025-07-02 04:52:33.952
2025-07-02 04:52:33.952 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.952 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.952 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.952 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.952 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.952
2025-07-02 04:52:33.952 # search for the pair that matches best without being identical
2025-07-02 04:52:33.952 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.952 # on junk -- unless we have to)
2025-07-02 04:52:33.952 for j in range(blo, bhi):
2025-07-02 04:52:33.952 bj = b[j]
2025-07-02 04:52:33.952 cruncher.set_seq2(bj)
2025-07-02 04:52:33.952 for i in range(alo, ahi):
2025-07-02 04:52:33.952 ai = a[i]
2025-07-02 04:52:33.952 if ai == bj:
2025-07-02 04:52:33.952 if eqi is None:
2025-07-02 04:52:33.952 eqi, eqj = i, j
2025-07-02 04:52:33.952 continue
2025-07-02 04:52:33.952 cruncher.set_seq1(ai)
2025-07-02 04:52:33.953 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.953 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.953 # compares by a factor of 3.
2025-07-02 04:52:33.953 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.953 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.953 # of the computation is cached by cruncher
2025-07-02 04:52:33.953 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.953 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.953 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.953 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.953 if best_ratio < cutoff:
2025-07-02 04:52:33.953 # no non-identical "pretty close" pair
2025-07-02 04:52:33.953 if eqi is None:
2025-07-02 04:52:33.953 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.953 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.953 return
2025-07-02 04:52:33.953 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.953 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.953 else:
2025-07-02 04:52:33.953 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.953 eqi = None
2025-07-02 04:52:33.954
2025-07-02 04:52:33.954 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.954 # identical
2025-07-02 04:52:33.954
2025-07-02 04:52:33.954 # pump out diffs from before the synch point
2025-07-02 04:52:33.954 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.954
2025-07-02 04:52:33.954 # do intraline marking on the synch pair
2025-07-02 04:52:33.954 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.954 if eqi is None:
2025-07-02 04:52:33.954 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.954 atags = btags = ""
2025-07-02 04:52:33.954 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.954 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.954 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.954 if tag == 'replace':
2025-07-02 04:52:33.954 atags += '^' * la
2025-07-02 04:52:33.954 btags += '^' * lb
2025-07-02 04:52:33.954 elif tag == 'delete':
2025-07-02 04:52:33.954 atags += '-' * la
2025-07-02 04:52:33.955 elif tag == 'insert':
2025-07-02 04:52:33.955 btags += '+' * lb
2025-07-02 04:52:33.955 elif tag == 'equal':
2025-07-02 04:52:33.955 atags += ' ' * la
2025-07-02 04:52:33.955 btags += ' ' * lb
2025-07-02 04:52:33.955 else:
2025-07-02 04:52:33.955 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.955 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.955 else:
2025-07-02 04:52:33.955 # the synch pair is identical
2025-07-02 04:52:33.955 yield ' ' + aelt
2025-07-02 04:52:33.955
2025-07-02 04:52:33.955 # pump out diffs from after the synch point
2025-07-02 04:52:33.955 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.955
2025-07-02 04:52:33.955 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.955 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.955
2025-07-02 04:52:33.955 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.956 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.956 alo = 501, ahi = 1101
2025-07-02 04:52:33.956 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.956 blo = 501, bhi = 1101
2025-07-02 04:52:33.956
2025-07-02 04:52:33.956 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.956 g = []
2025-07-02 04:52:33.956 if alo < ahi:
2025-07-02 04:52:33.956 if blo < bhi:
2025-07-02 04:52:33.956 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.956 else:
2025-07-02 04:52:33.956 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.956 elif blo < bhi:
2025-07-02 04:52:33.956 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.956
2025-07-02 04:52:33.956 > yield from g
2025-07-02 04:52:33.956
2025-07-02 04:52:33.956 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.956 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.956
2025-07-02 04:52:33.956 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.957 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.957 alo = 501, ahi = 1101
2025-07-02 04:52:33.957 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.957 blo = 501, bhi = 1101
2025-07-02 04:52:33.957
2025-07-02 04:52:33.957 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.957 r"""
2025-07-02 04:52:33.957 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.957 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.957 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.957 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.957
2025-07-02 04:52:33.957 Example:
2025-07-02 04:52:33.957
2025-07-02 04:52:33.957 >>> d = Differ()
2025-07-02 04:52:33.957 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.957 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.957 >>> print(''.join(results), end="")
2025-07-02 04:52:33.957 - abcDefghiJkl
2025-07-02 04:52:33.958 + abcdefGhijkl
2025-07-02 04:52:33.958 """
2025-07-02 04:52:33.958
2025-07-02 04:52:33.958 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.958 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.958 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.958 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.958 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.958
2025-07-02 04:52:33.958 # search for the pair that matches best without being identical
2025-07-02 04:52:33.958 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.958 # on junk -- unless we have to)
2025-07-02 04:52:33.958 for j in range(blo, bhi):
2025-07-02 04:52:33.958 bj = b[j]
2025-07-02 04:52:33.958 cruncher.set_seq2(bj)
2025-07-02 04:52:33.958 for i in range(alo, ahi):
2025-07-02 04:52:33.958 ai = a[i]
2025-07-02 04:52:33.958 if ai == bj:
2025-07-02 04:52:33.958 if eqi is None:
2025-07-02 04:52:33.958 eqi, eqj = i, j
2025-07-02 04:52:33.959 continue
2025-07-02 04:52:33.959 cruncher.set_seq1(ai)
2025-07-02 04:52:33.959 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.959 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.959 # compares by a factor of 3.
2025-07-02 04:52:33.959 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.959 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.959 # of the computation is cached by cruncher
2025-07-02 04:52:33.959 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.959 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.959 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.959 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.959 if best_ratio < cutoff:
2025-07-02 04:52:33.959 # no non-identical "pretty close" pair
2025-07-02 04:52:33.959 if eqi is None:
2025-07-02 04:52:33.959 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.959 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.959 return
2025-07-02 04:52:33.959 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.959 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.960 else:
2025-07-02 04:52:33.960 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.960 eqi = None
2025-07-02 04:52:33.960
2025-07-02 04:52:33.960 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.960 # identical
2025-07-02 04:52:33.960
2025-07-02 04:52:33.960 # pump out diffs from before the synch point
2025-07-02 04:52:33.960 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.960
2025-07-02 04:52:33.960 # do intraline marking on the synch pair
2025-07-02 04:52:33.960 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.960 if eqi is None:
2025-07-02 04:52:33.960 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.960 atags = btags = ""
2025-07-02 04:52:33.960 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.960 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.960 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.960 if tag == 'replace':
2025-07-02 04:52:33.960 atags += '^' * la
2025-07-02 04:52:33.960 btags += '^' * lb
2025-07-02 04:52:33.961 elif tag == 'delete':
2025-07-02 04:52:33.961 atags += '-' * la
2025-07-02 04:52:33.961 elif tag == 'insert':
2025-07-02 04:52:33.961 btags += '+' * lb
2025-07-02 04:52:33.961 elif tag == 'equal':
2025-07-02 04:52:33.961 atags += ' ' * la
2025-07-02 04:52:33.961 btags += ' ' * lb
2025-07-02 04:52:33.961 else:
2025-07-02 04:52:33.961 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.961 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.961 else:
2025-07-02 04:52:33.961 # the synch pair is identical
2025-07-02 04:52:33.961 yield ' ' + aelt
2025-07-02 04:52:33.961
2025-07-02 04:52:33.961 # pump out diffs from after the synch point
2025-07-02 04:52:33.961 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.961
2025-07-02 04:52:33.961 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.961 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.961
2025-07-02 04:52:33.961 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.962 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.962 alo = 502, ahi = 1101
2025-07-02 04:52:33.962 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.962 blo = 502, bhi = 1101
2025-07-02 04:52:33.962
2025-07-02 04:52:33.962 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.962 g = []
2025-07-02 04:52:33.962 if alo < ahi:
2025-07-02 04:52:33.962 if blo < bhi:
2025-07-02 04:52:33.962 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.962 else:
2025-07-02 04:52:33.962 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.962 elif blo < bhi:
2025-07-02 04:52:33.962 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.962
2025-07-02 04:52:33.962 > yield from g
2025-07-02 04:52:33.962
2025-07-02 04:52:33.962 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.962 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.962
2025-07-02 04:52:33.962 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.963 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.963 alo = 502, ahi = 1101
2025-07-02 04:52:33.963 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.963 blo = 502, bhi = 1101
2025-07-02 04:52:33.963
2025-07-02 04:52:33.963 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.963 r"""
2025-07-02 04:52:33.963 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.963 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.963 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.963 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.963
2025-07-02 04:52:33.963 Example:
2025-07-02 04:52:33.963
2025-07-02 04:52:33.963 >>> d = Differ()
2025-07-02 04:52:33.963 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.963 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.963 >>> print(''.join(results), end="")
2025-07-02 04:52:33.963 - abcDefghiJkl
2025-07-02 04:52:33.964 + abcdefGhijkl
2025-07-02 04:52:33.964 """
2025-07-02 04:52:33.964
2025-07-02 04:52:33.964 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.964 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.964 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.964 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.964 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.964
2025-07-02 04:52:33.964 # search for the pair that matches best without being identical
2025-07-02 04:52:33.964 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.964 # on junk -- unless we have to)
2025-07-02 04:52:33.964 for j in range(blo, bhi):
2025-07-02 04:52:33.964 bj = b[j]
2025-07-02 04:52:33.964 cruncher.set_seq2(bj)
2025-07-02 04:52:33.964 for i in range(alo, ahi):
2025-07-02 04:52:33.964 ai = a[i]
2025-07-02 04:52:33.964 if ai == bj:
2025-07-02 04:52:33.965 if eqi is None:
2025-07-02 04:52:33.965 eqi, eqj = i, j
2025-07-02 04:52:33.965 continue
2025-07-02 04:52:33.965 cruncher.set_seq1(ai)
2025-07-02 04:52:33.965 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.965 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.965 # compares by a factor of 3.
2025-07-02 04:52:33.965 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.965 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.965 # of the computation is cached by cruncher
2025-07-02 04:52:33.965 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.965 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.965 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.965 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.965 if best_ratio < cutoff:
2025-07-02 04:52:33.965 # no non-identical "pretty close" pair
2025-07-02 04:52:33.965 if eqi is None:
2025-07-02 04:52:33.965 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.965 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.965 return
2025-07-02 04:52:33.965 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.965 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.966 else:
2025-07-02 04:52:33.966 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.966 eqi = None
2025-07-02 04:52:33.966
2025-07-02 04:52:33.966 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.966 # identical
2025-07-02 04:52:33.966
2025-07-02 04:52:33.966 # pump out diffs from before the synch point
2025-07-02 04:52:33.966 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.966
2025-07-02 04:52:33.966 # do intraline marking on the synch pair
2025-07-02 04:52:33.966 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.966 if eqi is None:
2025-07-02 04:52:33.966 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.966 atags = btags = ""
2025-07-02 04:52:33.966 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.966 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.966 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.966 if tag == 'replace':
2025-07-02 04:52:33.966 atags += '^' * la
2025-07-02 04:52:33.966 btags += '^' * lb
2025-07-02 04:52:33.967 elif tag == 'delete':
2025-07-02 04:52:33.967 atags += '-' * la
2025-07-02 04:52:33.967 elif tag == 'insert':
2025-07-02 04:52:33.967 btags += '+' * lb
2025-07-02 04:52:33.967 elif tag == 'equal':
2025-07-02 04:52:33.967 atags += ' ' * la
2025-07-02 04:52:33.967 btags += ' ' * lb
2025-07-02 04:52:33.967 else:
2025-07-02 04:52:33.967 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.967 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.967 else:
2025-07-02 04:52:33.967 # the synch pair is identical
2025-07-02 04:52:33.967 yield ' ' + aelt
2025-07-02 04:52:33.967
2025-07-02 04:52:33.967 # pump out diffs from after the synch point
2025-07-02 04:52:33.967 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.967
2025-07-02 04:52:33.967 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.967 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.968
2025-07-02 04:52:33.968 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.968 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.968 alo = 503, ahi = 1101
2025-07-02 04:52:33.968 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.968 blo = 503, bhi = 1101
2025-07-02 04:52:33.968
2025-07-02 04:52:33.968 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.968 g = []
2025-07-02 04:52:33.968 if alo < ahi:
2025-07-02 04:52:33.968 if blo < bhi:
2025-07-02 04:52:33.968 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.968 else:
2025-07-02 04:52:33.968 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.968 elif blo < bhi:
2025-07-02 04:52:33.968 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.968
2025-07-02 04:52:33.968 > yield from g
2025-07-02 04:52:33.968
2025-07-02 04:52:33.968 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.969 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.969
2025-07-02 04:52:33.969 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.969 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.969 alo = 503, ahi = 1101
2025-07-02 04:52:33.969 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.969 blo = 503, bhi = 1101
2025-07-02 04:52:33.969
2025-07-02 04:52:33.969 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.969 r"""
2025-07-02 04:52:33.969 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.969 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.969 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.969 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.969
2025-07-02 04:52:33.969 Example:
2025-07-02 04:52:33.969
2025-07-02 04:52:33.969 >>> d = Differ()
2025-07-02 04:52:33.969 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.969 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.969 >>> print(''.join(results), end="")
2025-07-02 04:52:33.970 - abcDefghiJkl
2025-07-02 04:52:33.970 + abcdefGhijkl
2025-07-02 04:52:33.970 """
2025-07-02 04:52:33.970
2025-07-02 04:52:33.970 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.970 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.970 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.970 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.970 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.970
2025-07-02 04:52:33.970 # search for the pair that matches best without being identical
2025-07-02 04:52:33.970 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.970 # on junk -- unless we have to)
2025-07-02 04:52:33.970 for j in range(blo, bhi):
2025-07-02 04:52:33.970 bj = b[j]
2025-07-02 04:52:33.970 cruncher.set_seq2(bj)
2025-07-02 04:52:33.970 for i in range(alo, ahi):
2025-07-02 04:52:33.970 ai = a[i]
2025-07-02 04:52:33.970 if ai == bj:
2025-07-02 04:52:33.971 if eqi is None:
2025-07-02 04:52:33.971 eqi, eqj = i, j
2025-07-02 04:52:33.971 continue
2025-07-02 04:52:33.971 cruncher.set_seq1(ai)
2025-07-02 04:52:33.971 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.971 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.971 # compares by a factor of 3.
2025-07-02 04:52:33.971 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.971 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.971 # of the computation is cached by cruncher
2025-07-02 04:52:33.971 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.971 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.971 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.971 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.971 if best_ratio < cutoff:
2025-07-02 04:52:33.971 # no non-identical "pretty close" pair
2025-07-02 04:52:33.971 if eqi is None:
2025-07-02 04:52:33.971 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.971 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.971 return
2025-07-02 04:52:33.972 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.972 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.972 else:
2025-07-02 04:52:33.972 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.972 eqi = None
2025-07-02 04:52:33.972
2025-07-02 04:52:33.972 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.972 # identical
2025-07-02 04:52:33.972
2025-07-02 04:52:33.972 # pump out diffs from before the synch point
2025-07-02 04:52:33.972 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.972
2025-07-02 04:52:33.972 # do intraline marking on the synch pair
2025-07-02 04:52:33.972 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.972 if eqi is None:
2025-07-02 04:52:33.972 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.972 atags = btags = ""
2025-07-02 04:52:33.972 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.972 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.972 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.972 if tag == 'replace':
2025-07-02 04:52:33.973 atags += '^' * la
2025-07-02 04:52:33.973 btags += '^' * lb
2025-07-02 04:52:33.973 elif tag == 'delete':
2025-07-02 04:52:33.973 atags += '-' * la
2025-07-02 04:52:33.973 elif tag == 'insert':
2025-07-02 04:52:33.973 btags += '+' * lb
2025-07-02 04:52:33.973 elif tag == 'equal':
2025-07-02 04:52:33.973 atags += ' ' * la
2025-07-02 04:52:33.973 btags += ' ' * lb
2025-07-02 04:52:33.973 else:
2025-07-02 04:52:33.973 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.973 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.973 else:
2025-07-02 04:52:33.973 # the synch pair is identical
2025-07-02 04:52:33.973 yield ' ' + aelt
2025-07-02 04:52:33.973
2025-07-02 04:52:33.973 # pump out diffs from after the synch point
2025-07-02 04:52:33.973 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.973
2025-07-02 04:52:33.973 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.973 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.974
2025-07-02 04:52:33.974 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.974 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.974 alo = 504, ahi = 1101
2025-07-02 04:52:33.974 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.974 blo = 504, bhi = 1101
2025-07-02 04:52:33.974
2025-07-02 04:52:33.974 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.974 g = []
2025-07-02 04:52:33.974 if alo < ahi:
2025-07-02 04:52:33.974 if blo < bhi:
2025-07-02 04:52:33.974 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.974 else:
2025-07-02 04:52:33.974 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.974 elif blo < bhi:
2025-07-02 04:52:33.974 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.974
2025-07-02 04:52:33.974 > yield from g
2025-07-02 04:52:33.974
2025-07-02 04:52:33.974 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.974 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.975
2025-07-02 04:52:33.975 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.975 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.975 alo = 504, ahi = 1101
2025-07-02 04:52:33.975 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.975 blo = 504, bhi = 1101
2025-07-02 04:52:33.975
2025-07-02 04:52:33.975 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.975 r"""
2025-07-02 04:52:33.975 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.975 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.975 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.975 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.975
2025-07-02 04:52:33.975 Example:
2025-07-02 04:52:33.975
2025-07-02 04:52:33.975 >>> d = Differ()
2025-07-02 04:52:33.975 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.975 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.975 >>> print(''.join(results), end="")
2025-07-02 04:52:33.975 - abcDefghiJkl
2025-07-02 04:52:33.976 + abcdefGhijkl
2025-07-02 04:52:33.976 """
2025-07-02 04:52:33.976
2025-07-02 04:52:33.976 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.976 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.976 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.976 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.976 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.976
2025-07-02 04:52:33.976 # search for the pair that matches best without being identical
2025-07-02 04:52:33.976 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.976 # on junk -- unless we have to)
2025-07-02 04:52:33.976 for j in range(blo, bhi):
2025-07-02 04:52:33.976 bj = b[j]
2025-07-02 04:52:33.976 cruncher.set_seq2(bj)
2025-07-02 04:52:33.976 for i in range(alo, ahi):
2025-07-02 04:52:33.976 ai = a[i]
2025-07-02 04:52:33.976 if ai == bj:
2025-07-02 04:52:33.976 if eqi is None:
2025-07-02 04:52:33.976 eqi, eqj = i, j
2025-07-02 04:52:33.977 continue
2025-07-02 04:52:33.977 cruncher.set_seq1(ai)
2025-07-02 04:52:33.977 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.977 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.977 # compares by a factor of 3.
2025-07-02 04:52:33.977 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.977 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.977 # of the computation is cached by cruncher
2025-07-02 04:52:33.977 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.977 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.977 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.977 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.977 if best_ratio < cutoff:
2025-07-02 04:52:33.977 # no non-identical "pretty close" pair
2025-07-02 04:52:33.977 if eqi is None:
2025-07-02 04:52:33.977 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.977 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.977 return
2025-07-02 04:52:33.977 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.977 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.977 else:
2025-07-02 04:52:33.978 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.978 eqi = None
2025-07-02 04:52:33.978
2025-07-02 04:52:33.978 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.978 # identical
2025-07-02 04:52:33.978
2025-07-02 04:52:33.978 # pump out diffs from before the synch point
2025-07-02 04:52:33.978 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.978
2025-07-02 04:52:33.978 # do intraline marking on the synch pair
2025-07-02 04:52:33.978 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.978 if eqi is None:
2025-07-02 04:52:33.978 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.978 atags = btags = ""
2025-07-02 04:52:33.978 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.978 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.978 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.978 if tag == 'replace':
2025-07-02 04:52:33.978 atags += '^' * la
2025-07-02 04:52:33.978 btags += '^' * lb
2025-07-02 04:52:33.978 elif tag == 'delete':
2025-07-02 04:52:33.978 atags += '-' * la
2025-07-02 04:52:33.979 elif tag == 'insert':
2025-07-02 04:52:33.979 btags += '+' * lb
2025-07-02 04:52:33.979 elif tag == 'equal':
2025-07-02 04:52:33.979 atags += ' ' * la
2025-07-02 04:52:33.979 btags += ' ' * lb
2025-07-02 04:52:33.979 else:
2025-07-02 04:52:33.979 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.979 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.979 else:
2025-07-02 04:52:33.979 # the synch pair is identical
2025-07-02 04:52:33.979 yield ' ' + aelt
2025-07-02 04:52:33.979
2025-07-02 04:52:33.979 # pump out diffs from after the synch point
2025-07-02 04:52:33.979 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.979
2025-07-02 04:52:33.979 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.979 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.979
2025-07-02 04:52:33.979 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.979 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.980 alo = 505, ahi = 1101
2025-07-02 04:52:33.980 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.980 blo = 505, bhi = 1101
2025-07-02 04:52:33.980
2025-07-02 04:52:33.980 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.980 g = []
2025-07-02 04:52:33.980 if alo < ahi:
2025-07-02 04:52:33.980 if blo < bhi:
2025-07-02 04:52:33.980 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.980 else:
2025-07-02 04:52:33.980 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.980 elif blo < bhi:
2025-07-02 04:52:33.980 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.980
2025-07-02 04:52:33.980 > yield from g
2025-07-02 04:52:33.980
2025-07-02 04:52:33.980 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.980 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.980
2025-07-02 04:52:33.980 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.981 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.981 alo = 505, ahi = 1101
2025-07-02 04:52:33.981 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.981 blo = 505, bhi = 1101
2025-07-02 04:52:33.981
2025-07-02 04:52:33.981 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.981 r"""
2025-07-02 04:52:33.981 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.981 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.981 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.981 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.981
2025-07-02 04:52:33.981 Example:
2025-07-02 04:52:33.981
2025-07-02 04:52:33.981 >>> d = Differ()
2025-07-02 04:52:33.981 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.981 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.981 >>> print(''.join(results), end="")
2025-07-02 04:52:33.981 - abcDefghiJkl
2025-07-02 04:52:33.981 + abcdefGhijkl
2025-07-02 04:52:33.982 """
2025-07-02 04:52:33.982
2025-07-02 04:52:33.982 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.982 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.982 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.982 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.982 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.982
2025-07-02 04:52:33.982 # search for the pair that matches best without being identical
2025-07-02 04:52:33.982 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.982 # on junk -- unless we have to)
2025-07-02 04:52:33.982 for j in range(blo, bhi):
2025-07-02 04:52:33.982 bj = b[j]
2025-07-02 04:52:33.982 cruncher.set_seq2(bj)
2025-07-02 04:52:33.982 for i in range(alo, ahi):
2025-07-02 04:52:33.982 ai = a[i]
2025-07-02 04:52:33.982 if ai == bj:
2025-07-02 04:52:33.982 if eqi is None:
2025-07-02 04:52:33.982 eqi, eqj = i, j
2025-07-02 04:52:33.982 continue
2025-07-02 04:52:33.983 cruncher.set_seq1(ai)
2025-07-02 04:52:33.983 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.983 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.983 # compares by a factor of 3.
2025-07-02 04:52:33.983 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.983 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.983 # of the computation is cached by cruncher
2025-07-02 04:52:33.983 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.983 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.983 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.983 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.983 if best_ratio < cutoff:
2025-07-02 04:52:33.983 # no non-identical "pretty close" pair
2025-07-02 04:52:33.983 if eqi is None:
2025-07-02 04:52:33.983 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.983 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.983 return
2025-07-02 04:52:33.983 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.983 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.983 else:
2025-07-02 04:52:33.984 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.984 eqi = None
2025-07-02 04:52:33.984
2025-07-02 04:52:33.984 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.984 # identical
2025-07-02 04:52:33.984
2025-07-02 04:52:33.984 # pump out diffs from before the synch point
2025-07-02 04:52:33.984 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.984
2025-07-02 04:52:33.984 # do intraline marking on the synch pair
2025-07-02 04:52:33.984 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.984 if eqi is None:
2025-07-02 04:52:33.984 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.984 atags = btags = ""
2025-07-02 04:52:33.984 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.984 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.984 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.984 if tag == 'replace':
2025-07-02 04:52:33.984 atags += '^' * la
2025-07-02 04:52:33.984 btags += '^' * lb
2025-07-02 04:52:33.984 elif tag == 'delete':
2025-07-02 04:52:33.985 atags += '-' * la
2025-07-02 04:52:33.985 elif tag == 'insert':
2025-07-02 04:52:33.985 btags += '+' * lb
2025-07-02 04:52:33.985 elif tag == 'equal':
2025-07-02 04:52:33.985 atags += ' ' * la
2025-07-02 04:52:33.985 btags += ' ' * lb
2025-07-02 04:52:33.985 else:
2025-07-02 04:52:33.985 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.985 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.985 else:
2025-07-02 04:52:33.985 # the synch pair is identical
2025-07-02 04:52:33.985 yield ' ' + aelt
2025-07-02 04:52:33.985
2025-07-02 04:52:33.985 # pump out diffs from after the synch point
2025-07-02 04:52:33.985 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.985
2025-07-02 04:52:33.985 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.985 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.985
2025-07-02 04:52:33.985 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.985 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.986 alo = 506, ahi = 1101
2025-07-02 04:52:33.986 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.986 blo = 506, bhi = 1101
2025-07-02 04:52:33.986
2025-07-02 04:52:33.986 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.986 g = []
2025-07-02 04:52:33.986 if alo < ahi:
2025-07-02 04:52:33.986 if blo < bhi:
2025-07-02 04:52:33.986 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.986 else:
2025-07-02 04:52:33.986 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.986 elif blo < bhi:
2025-07-02 04:52:33.986 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.986
2025-07-02 04:52:33.986 > yield from g
2025-07-02 04:52:33.986
2025-07-02 04:52:33.986 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.986 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.986
2025-07-02 04:52:33.986 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.986 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.987 alo = 506, ahi = 1101
2025-07-02 04:52:33.987 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.987 blo = 506, bhi = 1101
2025-07-02 04:52:33.987
2025-07-02 04:52:33.987 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.987 r"""
2025-07-02 04:52:33.987 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.987 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.987 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.987 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.987
2025-07-02 04:52:33.987 Example:
2025-07-02 04:52:33.987
2025-07-02 04:52:33.987 >>> d = Differ()
2025-07-02 04:52:33.987 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.987 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.987 >>> print(''.join(results), end="")
2025-07-02 04:52:33.987 - abcDefghiJkl
2025-07-02 04:52:33.987 + abcdefGhijkl
2025-07-02 04:52:33.988 """
2025-07-02 04:52:33.988
2025-07-02 04:52:33.988 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.988 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.988 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.988 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.988 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.988
2025-07-02 04:52:33.988 # search for the pair that matches best without being identical
2025-07-02 04:52:33.988 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.988 # on junk -- unless we have to)
2025-07-02 04:52:33.988 for j in range(blo, bhi):
2025-07-02 04:52:33.988 bj = b[j]
2025-07-02 04:52:33.988 cruncher.set_seq2(bj)
2025-07-02 04:52:33.988 for i in range(alo, ahi):
2025-07-02 04:52:33.988 ai = a[i]
2025-07-02 04:52:33.988 if ai == bj:
2025-07-02 04:52:33.988 if eqi is None:
2025-07-02 04:52:33.988 eqi, eqj = i, j
2025-07-02 04:52:33.988 continue
2025-07-02 04:52:33.989 cruncher.set_seq1(ai)
2025-07-02 04:52:33.989 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.989 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.989 # compares by a factor of 3.
2025-07-02 04:52:33.989 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.989 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.989 # of the computation is cached by cruncher
2025-07-02 04:52:33.989 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.989 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.989 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.989 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.989 if best_ratio < cutoff:
2025-07-02 04:52:33.989 # no non-identical "pretty close" pair
2025-07-02 04:52:33.989 if eqi is None:
2025-07-02 04:52:33.989 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.989 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.989 return
2025-07-02 04:52:33.989 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.989 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.989 else:
2025-07-02 04:52:33.989 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.990 eqi = None
2025-07-02 04:52:33.990
2025-07-02 04:52:33.990 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.990 # identical
2025-07-02 04:52:33.990
2025-07-02 04:52:33.990 # pump out diffs from before the synch point
2025-07-02 04:52:33.990 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.990
2025-07-02 04:52:33.990 # do intraline marking on the synch pair
2025-07-02 04:52:33.990 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.990 if eqi is None:
2025-07-02 04:52:33.990 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.990 atags = btags = ""
2025-07-02 04:52:33.990 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.990 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.990 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.990 if tag == 'replace':
2025-07-02 04:52:33.990 atags += '^' * la
2025-07-02 04:52:33.990 btags += '^' * lb
2025-07-02 04:52:33.990 elif tag == 'delete':
2025-07-02 04:52:33.990 atags += '-' * la
2025-07-02 04:52:33.991 elif tag == 'insert':
2025-07-02 04:52:33.991 btags += '+' * lb
2025-07-02 04:52:33.991 elif tag == 'equal':
2025-07-02 04:52:33.991 atags += ' ' * la
2025-07-02 04:52:33.991 btags += ' ' * lb
2025-07-02 04:52:33.991 else:
2025-07-02 04:52:33.991 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.991 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.991 else:
2025-07-02 04:52:33.991 # the synch pair is identical
2025-07-02 04:52:33.991 yield ' ' + aelt
2025-07-02 04:52:33.991
2025-07-02 04:52:33.991 # pump out diffs from after the synch point
2025-07-02 04:52:33.991 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.991
2025-07-02 04:52:33.991 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.991 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.991
2025-07-02 04:52:33.991 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.991 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.991 alo = 507, ahi = 1101
2025-07-02 04:52:33.992 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.992 blo = 507, bhi = 1101
2025-07-02 04:52:33.992
2025-07-02 04:52:33.992 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.992 g = []
2025-07-02 04:52:33.992 if alo < ahi:
2025-07-02 04:52:33.992 if blo < bhi:
2025-07-02 04:52:33.992 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.992 else:
2025-07-02 04:52:33.992 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.992 elif blo < bhi:
2025-07-02 04:52:33.992 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.992
2025-07-02 04:52:33.992 > yield from g
2025-07-02 04:52:33.992
2025-07-02 04:52:33.992 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.992 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.992
2025-07-02 04:52:33.992 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.992 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.992 alo = 507, ahi = 1101
2025-07-02 04:52:33.992 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.993 blo = 507, bhi = 1101
2025-07-02 04:52:33.993
2025-07-02 04:52:33.993 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.993 r"""
2025-07-02 04:52:33.993 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.993 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.993 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.993 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.993
2025-07-02 04:52:33.993 Example:
2025-07-02 04:52:33.993
2025-07-02 04:52:33.993 >>> d = Differ()
2025-07-02 04:52:33.993 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.993 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.993 >>> print(''.join(results), end="")
2025-07-02 04:52:33.993 - abcDefghiJkl
2025-07-02 04:52:33.993 + abcdefGhijkl
2025-07-02 04:52:33.993 """
2025-07-02 04:52:33.993
2025-07-02 04:52:33.994 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:33.994 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:33.994 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:33.994 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:33.994 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:33.994
2025-07-02 04:52:33.994 # search for the pair that matches best without being identical
2025-07-02 04:52:33.994 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:33.994 # on junk -- unless we have to)
2025-07-02 04:52:33.994 for j in range(blo, bhi):
2025-07-02 04:52:33.994 bj = b[j]
2025-07-02 04:52:33.994 cruncher.set_seq2(bj)
2025-07-02 04:52:33.994 for i in range(alo, ahi):
2025-07-02 04:52:33.994 ai = a[i]
2025-07-02 04:52:33.994 if ai == bj:
2025-07-02 04:52:33.994 if eqi is None:
2025-07-02 04:52:33.994 eqi, eqj = i, j
2025-07-02 04:52:33.994 continue
2025-07-02 04:52:33.994 cruncher.set_seq1(ai)
2025-07-02 04:52:33.994 # computing similarity is expensive, so use the quick
2025-07-02 04:52:33.994 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:33.994 # compares by a factor of 3.
2025-07-02 04:52:33.995 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:33.995 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:33.995 # of the computation is cached by cruncher
2025-07-02 04:52:33.995 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:33.995 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:33.995 cruncher.ratio() > best_ratio:
2025-07-02 04:52:33.995 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:33.995 if best_ratio < cutoff:
2025-07-02 04:52:33.995 # no non-identical "pretty close" pair
2025-07-02 04:52:33.995 if eqi is None:
2025-07-02 04:52:33.995 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:33.995 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.995 return
2025-07-02 04:52:33.995 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:33.995 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:33.995 else:
2025-07-02 04:52:33.995 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:33.995 eqi = None
2025-07-02 04:52:33.995
2025-07-02 04:52:33.995 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:33.996 # identical
2025-07-02 04:52:33.996
2025-07-02 04:52:33.996 # pump out diffs from before the synch point
2025-07-02 04:52:33.996 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:33.996
2025-07-02 04:52:33.996 # do intraline marking on the synch pair
2025-07-02 04:52:33.996 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:33.996 if eqi is None:
2025-07-02 04:52:33.996 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:33.996 atags = btags = ""
2025-07-02 04:52:33.996 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:33.996 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:33.996 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:33.996 if tag == 'replace':
2025-07-02 04:52:33.996 atags += '^' * la
2025-07-02 04:52:33.996 btags += '^' * lb
2025-07-02 04:52:33.996 elif tag == 'delete':
2025-07-02 04:52:33.996 atags += '-' * la
2025-07-02 04:52:33.996 elif tag == 'insert':
2025-07-02 04:52:33.996 btags += '+' * lb
2025-07-02 04:52:33.996 elif tag == 'equal':
2025-07-02 04:52:33.997 atags += ' ' * la
2025-07-02 04:52:33.997 btags += ' ' * lb
2025-07-02 04:52:33.997 else:
2025-07-02 04:52:33.997 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:33.997 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:33.997 else:
2025-07-02 04:52:33.997 # the synch pair is identical
2025-07-02 04:52:33.997 yield ' ' + aelt
2025-07-02 04:52:33.997
2025-07-02 04:52:33.997 # pump out diffs from after the synch point
2025-07-02 04:52:33.997 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:33.997
2025-07-02 04:52:33.997 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:33.997 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.997
2025-07-02 04:52:33.997 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.997 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.997 alo = 510, ahi = 1101
2025-07-02 04:52:33.997 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.998 blo = 510, bhi = 1101
2025-07-02 04:52:33.998
2025-07-02 04:52:33.998 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.998 g = []
2025-07-02 04:52:33.998 if alo < ahi:
2025-07-02 04:52:33.998 if blo < bhi:
2025-07-02 04:52:33.998 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:33.998 else:
2025-07-02 04:52:33.998 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:33.998 elif blo < bhi:
2025-07-02 04:52:33.998 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:33.998
2025-07-02 04:52:33.998 > yield from g
2025-07-02 04:52:33.998
2025-07-02 04:52:33.998 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:33.998 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:33.998
2025-07-02 04:52:33.998 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:33.998 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:33.998 alo = 510, ahi = 1101
2025-07-02 04:52:33.998 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:33.999 blo = 510, bhi = 1101
2025-07-02 04:52:33.999
2025-07-02 04:52:33.999 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:33.999 r"""
2025-07-02 04:52:33.999 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:33.999 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:33.999 synch point, and intraline difference marking is done on the
2025-07-02 04:52:33.999 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:33.999
2025-07-02 04:52:33.999 Example:
2025-07-02 04:52:33.999
2025-07-02 04:52:33.999 >>> d = Differ()
2025-07-02 04:52:33.999 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:33.999 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:33.999 >>> print(''.join(results), end="")
2025-07-02 04:52:33.999 - abcDefghiJkl
2025-07-02 04:52:33.999 + abcdefGhijkl
2025-07-02 04:52:34.000 """
2025-07-02 04:52:34.000
2025-07-02 04:52:34.000 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:34.000 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:34.000 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:34.000 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:34.000 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:34.000
2025-07-02 04:52:34.000 # search for the pair that matches best without being identical
2025-07-02 04:52:34.000 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:34.000 # on junk -- unless we have to)
2025-07-02 04:52:34.000 for j in range(blo, bhi):
2025-07-02 04:52:34.000 bj = b[j]
2025-07-02 04:52:34.000 cruncher.set_seq2(bj)
2025-07-02 04:52:34.000 for i in range(alo, ahi):
2025-07-02 04:52:34.000 ai = a[i]
2025-07-02 04:52:34.000 if ai == bj:
2025-07-02 04:52:34.000 if eqi is None:
2025-07-02 04:52:34.000 eqi, eqj = i, j
2025-07-02 04:52:34.000 continue
2025-07-02 04:52:34.000 cruncher.set_seq1(ai)
2025-07-02 04:52:34.001 # computing similarity is expensive, so use the quick
2025-07-02 04:52:34.001 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:34.001 # compares by a factor of 3.
2025-07-02 04:52:34.001 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:34.001 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:34.001 # of the computation is cached by cruncher
2025-07-02 04:52:34.001 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:34.001 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:34.001 cruncher.ratio() > best_ratio:
2025-07-02 04:52:34.001 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:34.001 if best_ratio < cutoff:
2025-07-02 04:52:34.001 # no non-identical "pretty close" pair
2025-07-02 04:52:34.001 if eqi is None:
2025-07-02 04:52:34.001 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:34.001 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.001 return
2025-07-02 04:52:34.001 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:34.001 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:34.001 else:
2025-07-02 04:52:34.001 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:34.001 eqi = None
2025-07-02 04:52:34.001
2025-07-02 04:52:34.002 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:34.002 # identical
2025-07-02 04:52:34.002
2025-07-02 04:52:34.002 # pump out diffs from before the synch point
2025-07-02 04:52:34.002 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:34.002
2025-07-02 04:52:34.002 # do intraline marking on the synch pair
2025-07-02 04:52:34.002 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:34.002 if eqi is None:
2025-07-02 04:52:34.002 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:34.002 atags = btags = ""
2025-07-02 04:52:34.002 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:34.002 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:34.002 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:34.002 if tag == 'replace':
2025-07-02 04:52:34.002 atags += '^' * la
2025-07-02 04:52:34.002 btags += '^' * lb
2025-07-02 04:52:34.002 elif tag == 'delete':
2025-07-02 04:52:34.002 atags += '-' * la
2025-07-02 04:52:34.002 elif tag == 'insert':
2025-07-02 04:52:34.002 btags += '+' * lb
2025-07-02 04:52:34.003 elif tag == 'equal':
2025-07-02 04:52:34.003 atags += ' ' * la
2025-07-02 04:52:34.003 btags += ' ' * lb
2025-07-02 04:52:34.003 else:
2025-07-02 04:52:34.003 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:34.003 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:34.003 else:
2025-07-02 04:52:34.003 # the synch pair is identical
2025-07-02 04:52:34.003 yield ' ' + aelt
2025-07-02 04:52:34.003
2025-07-02 04:52:34.003 # pump out diffs from after the synch point
2025-07-02 04:52:34.003 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:34.003
2025-07-02 04:52:34.003 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:34.003 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.003
2025-07-02 04:52:34.003 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.003 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.003 alo = 511, ahi = 1101
2025-07-02 04:52:34.003 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.003 blo = 511, bhi = 1101
2025-07-02 04:52:34.004
2025-07-02 04:52:34.004 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.004 g = []
2025-07-02 04:52:34.004 if alo < ahi:
2025-07-02 04:52:34.004 if blo < bhi:
2025-07-02 04:52:34.004 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.004 else:
2025-07-02 04:52:34.004 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:34.004 elif blo < bhi:
2025-07-02 04:52:34.004 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:34.004
2025-07-02 04:52:34.004 > yield from g
2025-07-02 04:52:34.004
2025-07-02 04:52:34.004 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:34.004 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.004
2025-07-02 04:52:34.004 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.004 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.004 alo = 511, ahi = 1101
2025-07-02 04:52:34.004 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.005 blo = 511, bhi = 1101
2025-07-02 04:52:34.005
2025-07-02 04:52:34.005 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.005 r"""
2025-07-02 04:52:34.005 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:34.005 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:34.005 synch point, and intraline difference marking is done on the
2025-07-02 04:52:34.005 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:34.005
2025-07-02 04:52:34.005 Example:
2025-07-02 04:52:34.005
2025-07-02 04:52:34.005 >>> d = Differ()
2025-07-02 04:52:34.005 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:34.005 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:34.005 >>> print(''.join(results), end="")
2025-07-02 04:52:34.005 - abcDefghiJkl
2025-07-02 04:52:34.005 + abcdefGhijkl
2025-07-02 04:52:34.005 """
2025-07-02 04:52:34.006
2025-07-02 04:52:34.006 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:34.006 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:34.006 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:34.006 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:34.006 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:34.006
2025-07-02 04:52:34.006 # search for the pair that matches best without being identical
2025-07-02 04:52:34.006 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:34.006 # on junk -- unless we have to)
2025-07-02 04:52:34.006 for j in range(blo, bhi):
2025-07-02 04:52:34.006 bj = b[j]
2025-07-02 04:52:34.006 cruncher.set_seq2(bj)
2025-07-02 04:52:34.006 for i in range(alo, ahi):
2025-07-02 04:52:34.006 ai = a[i]
2025-07-02 04:52:34.006 if ai == bj:
2025-07-02 04:52:34.006 if eqi is None:
2025-07-02 04:52:34.006 eqi, eqj = i, j
2025-07-02 04:52:34.006 continue
2025-07-02 04:52:34.006 cruncher.set_seq1(ai)
2025-07-02 04:52:34.006 # computing similarity is expensive, so use the quick
2025-07-02 04:52:34.007 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:34.007 # compares by a factor of 3.
2025-07-02 04:52:34.007 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:34.007 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:34.007 # of the computation is cached by cruncher
2025-07-02 04:52:34.007 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:34.007 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:34.007 cruncher.ratio() > best_ratio:
2025-07-02 04:52:34.007 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:34.007 if best_ratio < cutoff:
2025-07-02 04:52:34.007 # no non-identical "pretty close" pair
2025-07-02 04:52:34.007 if eqi is None:
2025-07-02 04:52:34.007 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:34.007 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.007 return
2025-07-02 04:52:34.007 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:34.007 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:34.007 else:
2025-07-02 04:52:34.007 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:34.007 eqi = None
2025-07-02 04:52:34.007
2025-07-02 04:52:34.008 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:34.008 # identical
2025-07-02 04:52:34.008
2025-07-02 04:52:34.008 # pump out diffs from before the synch point
2025-07-02 04:52:34.008 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:34.008
2025-07-02 04:52:34.008 # do intraline marking on the synch pair
2025-07-02 04:52:34.008 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:34.008 if eqi is None:
2025-07-02 04:52:34.008 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:34.008 atags = btags = ""
2025-07-02 04:52:34.008 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:34.008 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:34.008 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:34.008 if tag == 'replace':
2025-07-02 04:52:34.008 atags += '^' * la
2025-07-02 04:52:34.008 btags += '^' * lb
2025-07-02 04:52:34.008 elif tag == 'delete':
2025-07-02 04:52:34.008 atags += '-' * la
2025-07-02 04:52:34.008 elif tag == 'insert':
2025-07-02 04:52:34.008 btags += '+' * lb
2025-07-02 04:52:34.009 elif tag == 'equal':
2025-07-02 04:52:34.009 atags += ' ' * la
2025-07-02 04:52:34.009 btags += ' ' * lb
2025-07-02 04:52:34.009 else:
2025-07-02 04:52:34.009 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:34.009 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:34.009 else:
2025-07-02 04:52:34.009 # the synch pair is identical
2025-07-02 04:52:34.009 yield ' ' + aelt
2025-07-02 04:52:34.009
2025-07-02 04:52:34.009 # pump out diffs from after the synch point
2025-07-02 04:52:34.009 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:34.009
2025-07-02 04:52:34.009 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:34.009 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.009
2025-07-02 04:52:34.009 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.009 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.009 alo = 512, ahi = 1101
2025-07-02 04:52:34.009 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.009 blo = 512, bhi = 1101
2025-07-02 04:52:34.010
2025-07-02 04:52:34.010 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.010 g = []
2025-07-02 04:52:34.010 if alo < ahi:
2025-07-02 04:52:34.010 if blo < bhi:
2025-07-02 04:52:34.010 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.010 else:
2025-07-02 04:52:34.010 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:34.010 elif blo < bhi:
2025-07-02 04:52:34.010 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:34.010
2025-07-02 04:52:34.010 > yield from g
2025-07-02 04:52:34.010
2025-07-02 04:52:34.010 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:34.010 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.010
2025-07-02 04:52:34.010 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.010 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.010 alo = 512, ahi = 1101
2025-07-02 04:52:34.010 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.010 blo = 512, bhi = 1101
2025-07-02 04:52:34.011
2025-07-02 04:52:34.011 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.011 r"""
2025-07-02 04:52:34.011 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:34.011 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:34.011 synch point, and intraline difference marking is done on the
2025-07-02 04:52:34.011 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:34.011
2025-07-02 04:52:34.011 Example:
2025-07-02 04:52:34.011
2025-07-02 04:52:34.011 >>> d = Differ()
2025-07-02 04:52:34.011 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:34.011 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:34.011 >>> print(''.join(results), end="")
2025-07-02 04:52:34.011 - abcDefghiJkl
2025-07-02 04:52:34.011 + abcdefGhijkl
2025-07-02 04:52:34.011 """
2025-07-02 04:52:34.011
2025-07-02 04:52:34.011 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:34.011 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:34.012 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:34.012 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:34.012 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:34.012
2025-07-02 04:52:34.012 # search for the pair that matches best without being identical
2025-07-02 04:52:34.012 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:34.012 # on junk -- unless we have to)
2025-07-02 04:52:34.012 for j in range(blo, bhi):
2025-07-02 04:52:34.012 bj = b[j]
2025-07-02 04:52:34.012 cruncher.set_seq2(bj)
2025-07-02 04:52:34.012 for i in range(alo, ahi):
2025-07-02 04:52:34.012 ai = a[i]
2025-07-02 04:52:34.012 if ai == bj:
2025-07-02 04:52:34.012 if eqi is None:
2025-07-02 04:52:34.012 eqi, eqj = i, j
2025-07-02 04:52:34.012 continue
2025-07-02 04:52:34.012 cruncher.set_seq1(ai)
2025-07-02 04:52:34.012 # computing similarity is expensive, so use the quick
2025-07-02 04:52:34.012 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:34.012 # compares by a factor of 3.
2025-07-02 04:52:34.013 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:34.013 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:34.013 # of the computation is cached by cruncher
2025-07-02 04:52:34.013 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:34.013 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:34.013 cruncher.ratio() > best_ratio:
2025-07-02 04:52:34.013 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:34.013 if best_ratio < cutoff:
2025-07-02 04:52:34.013 # no non-identical "pretty close" pair
2025-07-02 04:52:34.013 if eqi is None:
2025-07-02 04:52:34.013 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:34.013 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.013 return
2025-07-02 04:52:34.013 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:34.013 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:34.013 else:
2025-07-02 04:52:34.013 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:34.013 eqi = None
2025-07-02 04:52:34.013
2025-07-02 04:52:34.013 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:34.014 # identical
2025-07-02 04:52:34.014
2025-07-02 04:52:34.014 # pump out diffs from before the synch point
2025-07-02 04:52:34.014 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:34.014
2025-07-02 04:52:34.014 # do intraline marking on the synch pair
2025-07-02 04:52:34.014 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:34.014 if eqi is None:
2025-07-02 04:52:34.014 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:34.014 atags = btags = ""
2025-07-02 04:52:34.014 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:34.014 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:34.014 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:34.014 if tag == 'replace':
2025-07-02 04:52:34.014 atags += '^' * la
2025-07-02 04:52:34.014 btags += '^' * lb
2025-07-02 04:52:34.014 elif tag == 'delete':
2025-07-02 04:52:34.014 atags += '-' * la
2025-07-02 04:52:34.014 elif tag == 'insert':
2025-07-02 04:52:34.014 btags += '+' * lb
2025-07-02 04:52:34.014 elif tag == 'equal':
2025-07-02 04:52:34.015 atags += ' ' * la
2025-07-02 04:52:34.015 btags += ' ' * lb
2025-07-02 04:52:34.015 else:
2025-07-02 04:52:34.015 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:34.015 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:34.015 else:
2025-07-02 04:52:34.015 # the synch pair is identical
2025-07-02 04:52:34.015 yield ' ' + aelt
2025-07-02 04:52:34.015
2025-07-02 04:52:34.015 # pump out diffs from after the synch point
2025-07-02 04:52:34.015 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:34.015
2025-07-02 04:52:34.015 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:34.015 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.015
2025-07-02 04:52:34.015 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.015 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.015 alo = 513, ahi = 1101
2025-07-02 04:52:34.015 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.016 blo = 513, bhi = 1101
2025-07-02 04:52:34.016
2025-07-02 04:52:34.016 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.016 g = []
2025-07-02 04:52:34.016 if alo < ahi:
2025-07-02 04:52:34.016 if blo < bhi:
2025-07-02 04:52:34.016 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.016 else:
2025-07-02 04:52:34.016 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:34.016 elif blo < bhi:
2025-07-02 04:52:34.016 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:34.016
2025-07-02 04:52:34.016 > yield from g
2025-07-02 04:52:34.016
2025-07-02 04:52:34.016 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:34.016 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.016
2025-07-02 04:52:34.016 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.016 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.016 alo = 513, ahi = 1101
2025-07-02 04:52:34.017 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.017 blo = 513, bhi = 1101
2025-07-02 04:52:34.017
2025-07-02 04:52:34.017 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.017 r"""
2025-07-02 04:52:34.017 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:34.017 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:34.017 synch point, and intraline difference marking is done on the
2025-07-02 04:52:34.017 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:34.017
2025-07-02 04:52:34.017 Example:
2025-07-02 04:52:34.017
2025-07-02 04:52:34.017 >>> d = Differ()
2025-07-02 04:52:34.017 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:34.017 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:34.017 >>> print(''.join(results), end="")
2025-07-02 04:52:34.017 - abcDefghiJkl
2025-07-02 04:52:34.017 + abcdefGhijkl
2025-07-02 04:52:34.018 """
2025-07-02 04:52:34.018
2025-07-02 04:52:34.018 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:34.018 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:34.018 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:34.018 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:34.018 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:34.018
2025-07-02 04:52:34.018 # search for the pair that matches best without being identical
2025-07-02 04:52:34.018 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:34.018 # on junk -- unless we have to)
2025-07-02 04:52:34.018 for j in range(blo, bhi):
2025-07-02 04:52:34.018 bj = b[j]
2025-07-02 04:52:34.018 cruncher.set_seq2(bj)
2025-07-02 04:52:34.018 for i in range(alo, ahi):
2025-07-02 04:52:34.018 ai = a[i]
2025-07-02 04:52:34.018 if ai == bj:
2025-07-02 04:52:34.018 if eqi is None:
2025-07-02 04:52:34.018 eqi, eqj = i, j
2025-07-02 04:52:34.018 continue
2025-07-02 04:52:34.019 cruncher.set_seq1(ai)
2025-07-02 04:52:34.019 # computing similarity is expensive, so use the quick
2025-07-02 04:52:34.019 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:34.019 # compares by a factor of 3.
2025-07-02 04:52:34.019 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:34.019 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:34.019 # of the computation is cached by cruncher
2025-07-02 04:52:34.019 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:34.019 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:34.019 cruncher.ratio() > best_ratio:
2025-07-02 04:52:34.019 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:34.019 if best_ratio < cutoff:
2025-07-02 04:52:34.019 # no non-identical "pretty close" pair
2025-07-02 04:52:34.019 if eqi is None:
2025-07-02 04:52:34.019 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:34.019 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.019 return
2025-07-02 04:52:34.019 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:34.019 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:34.019 else:
2025-07-02 04:52:34.019 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:34.020 eqi = None
2025-07-02 04:52:34.020
2025-07-02 04:52:34.020 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:34.020 # identical
2025-07-02 04:52:34.020
2025-07-02 04:52:34.020 # pump out diffs from before the synch point
2025-07-02 04:52:34.020 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:34.020
2025-07-02 04:52:34.020 # do intraline marking on the synch pair
2025-07-02 04:52:34.020 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:34.020 if eqi is None:
2025-07-02 04:52:34.020 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:34.020 atags = btags = ""
2025-07-02 04:52:34.020 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:34.020 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:34.020 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:34.020 if tag == 'replace':
2025-07-02 04:52:34.020 atags += '^' * la
2025-07-02 04:52:34.020 btags += '^' * lb
2025-07-02 04:52:34.020 elif tag == 'delete':
2025-07-02 04:52:34.021 atags += '-' * la
2025-07-02 04:52:34.021 elif tag == 'insert':
2025-07-02 04:52:34.021 btags += '+' * lb
2025-07-02 04:52:34.021 elif tag == 'equal':
2025-07-02 04:52:34.021 atags += ' ' * la
2025-07-02 04:52:34.021 btags += ' ' * lb
2025-07-02 04:52:34.021 else:
2025-07-02 04:52:34.021 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:34.021 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:34.021 else:
2025-07-02 04:52:34.021 # the synch pair is identical
2025-07-02 04:52:34.021 yield ' ' + aelt
2025-07-02 04:52:34.021
2025-07-02 04:52:34.021 # pump out diffs from after the synch point
2025-07-02 04:52:34.021 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:34.021
2025-07-02 04:52:34.021 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:34.021 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.021
2025-07-02 04:52:34.021 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.022 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.022 alo = 514, ahi = 1101
2025-07-02 04:52:34.022 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.022 blo = 514, bhi = 1101
2025-07-02 04:52:34.022
2025-07-02 04:52:34.022 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.022 g = []
2025-07-02 04:52:34.022 if alo < ahi:
2025-07-02 04:52:34.022 if blo < bhi:
2025-07-02 04:52:34.022 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.022 else:
2025-07-02 04:52:34.022 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:34.022 elif blo < bhi:
2025-07-02 04:52:34.022 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:34.022
2025-07-02 04:52:34.022 > yield from g
2025-07-02 04:52:34.022
2025-07-02 04:52:34.022 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:34.022 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.022
2025-07-02 04:52:34.023 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.023 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.023 alo = 514, ahi = 1101
2025-07-02 04:52:34.023 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.023 blo = 514, bhi = 1101
2025-07-02 04:52:34.023
2025-07-02 04:52:34.023 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.023 r"""
2025-07-02 04:52:34.023 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:34.023 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:34.023 synch point, and intraline difference marking is done on the
2025-07-02 04:52:34.023 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:34.023
2025-07-02 04:52:34.023 Example:
2025-07-02 04:52:34.023
2025-07-02 04:52:34.023 >>> d = Differ()
2025-07-02 04:52:34.023 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:34.023 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:34.023 >>> print(''.join(results), end="")
2025-07-02 04:52:34.023 - abcDefghiJkl
2025-07-02 04:52:34.024 + abcdefGhijkl
2025-07-02 04:52:34.024 """
2025-07-02 04:52:34.024
2025-07-02 04:52:34.024 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:34.024 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:34.024 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:34.024 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:34.024 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:34.024
2025-07-02 04:52:34.024 # search for the pair that matches best without being identical
2025-07-02 04:52:34.024 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:34.024 # on junk -- unless we have to)
2025-07-02 04:52:34.024 for j in range(blo, bhi):
2025-07-02 04:52:34.024 bj = b[j]
2025-07-02 04:52:34.024 cruncher.set_seq2(bj)
2025-07-02 04:52:34.024 for i in range(alo, ahi):
2025-07-02 04:52:34.024 ai = a[i]
2025-07-02 04:52:34.024 if ai == bj:
2025-07-02 04:52:34.024 if eqi is None:
2025-07-02 04:52:34.025 eqi, eqj = i, j
2025-07-02 04:52:34.025 continue
2025-07-02 04:52:34.025 cruncher.set_seq1(ai)
2025-07-02 04:52:34.025 # computing similarity is expensive, so use the quick
2025-07-02 04:52:34.025 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:34.025 # compares by a factor of 3.
2025-07-02 04:52:34.025 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:34.025 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:34.025 # of the computation is cached by cruncher
2025-07-02 04:52:34.025 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:34.025 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:34.025 cruncher.ratio() > best_ratio:
2025-07-02 04:52:34.025 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:34.025 if best_ratio < cutoff:
2025-07-02 04:52:34.025 # no non-identical "pretty close" pair
2025-07-02 04:52:34.025 if eqi is None:
2025-07-02 04:52:34.025 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:34.025 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.025 return
2025-07-02 04:52:34.025 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:34.026 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:34.026 else:
2025-07-02 04:52:34.026 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:34.026 eqi = None
2025-07-02 04:52:34.026
2025-07-02 04:52:34.026 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:34.026 # identical
2025-07-02 04:52:34.026
2025-07-02 04:52:34.026 # pump out diffs from before the synch point
2025-07-02 04:52:34.026 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:34.026
2025-07-02 04:52:34.026 # do intraline marking on the synch pair
2025-07-02 04:52:34.026 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:34.026 if eqi is None:
2025-07-02 04:52:34.026 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:34.026 atags = btags = ""
2025-07-02 04:52:34.026 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:34.026 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:34.026 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:34.026 if tag == 'replace':
2025-07-02 04:52:34.026 atags += '^' * la
2025-07-02 04:52:34.027 btags += '^' * lb
2025-07-02 04:52:34.027 elif tag == 'delete':
2025-07-02 04:52:34.027 atags += '-' * la
2025-07-02 04:52:34.027 elif tag == 'insert':
2025-07-02 04:52:34.027 btags += '+' * lb
2025-07-02 04:52:34.027 elif tag == 'equal':
2025-07-02 04:52:34.027 atags += ' ' * la
2025-07-02 04:52:34.027 btags += ' ' * lb
2025-07-02 04:52:34.027 else:
2025-07-02 04:52:34.027 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:34.027 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:34.027 else:
2025-07-02 04:52:34.027 # the synch pair is identical
2025-07-02 04:52:34.027 yield ' ' + aelt
2025-07-02 04:52:34.027
2025-07-02 04:52:34.027 # pump out diffs from after the synch point
2025-07-02 04:52:34.027 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:34.027
2025-07-02 04:52:34.027 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:34.027 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.028
2025-07-02 04:52:34.028 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.028 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.028 alo = 515, ahi = 1101
2025-07-02 04:52:34.028 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.028 blo = 515, bhi = 1101
2025-07-02 04:52:34.028
2025-07-02 04:52:34.028 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.028 g = []
2025-07-02 04:52:34.028 if alo < ahi:
2025-07-02 04:52:34.028 if blo < bhi:
2025-07-02 04:52:34.028 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.028 else:
2025-07-02 04:52:34.028 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:34.028 elif blo < bhi:
2025-07-02 04:52:34.028 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:34.028
2025-07-02 04:52:34.028 > yield from g
2025-07-02 04:52:34.028
2025-07-02 04:52:34.028 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:34.028 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.029
2025-07-02 04:52:34.029 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.029 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.029 alo = 515, ahi = 1101
2025-07-02 04:52:34.029 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.029 blo = 515, bhi = 1101
2025-07-02 04:52:34.029
2025-07-02 04:52:34.029 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.029 r"""
2025-07-02 04:52:34.029 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:34.029 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:34.029 synch point, and intraline difference marking is done on the
2025-07-02 04:52:34.029 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:34.029
2025-07-02 04:52:34.029 Example:
2025-07-02 04:52:34.029
2025-07-02 04:52:34.029 >>> d = Differ()
2025-07-02 04:52:34.029 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:34.029 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:34.030 >>> print(''.join(results), end="")
2025-07-02 04:52:34.030 - abcDefghiJkl
2025-07-02 04:52:34.030 + abcdefGhijkl
2025-07-02 04:52:34.030 """
2025-07-02 04:52:34.030
2025-07-02 04:52:34.030 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:34.030 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:34.030 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:34.030 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:34.030 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:34.030
2025-07-02 04:52:34.030 # search for the pair that matches best without being identical
2025-07-02 04:52:34.030 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:34.030 # on junk -- unless we have to)
2025-07-02 04:52:34.030 for j in range(blo, bhi):
2025-07-02 04:52:34.030 bj = b[j]
2025-07-02 04:52:34.030 cruncher.set_seq2(bj)
2025-07-02 04:52:34.031 for i in range(alo, ahi):
2025-07-02 04:52:34.031 ai = a[i]
2025-07-02 04:52:34.031 if ai == bj:
2025-07-02 04:52:34.031 if eqi is None:
2025-07-02 04:52:34.031 eqi, eqj = i, j
2025-07-02 04:52:34.031 continue
2025-07-02 04:52:34.031 cruncher.set_seq1(ai)
2025-07-02 04:52:34.031 # computing similarity is expensive, so use the quick
2025-07-02 04:52:34.031 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:34.031 # compares by a factor of 3.
2025-07-02 04:52:34.031 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:34.031 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:34.031 # of the computation is cached by cruncher
2025-07-02 04:52:34.031 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:34.031 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:34.031 cruncher.ratio() > best_ratio:
2025-07-02 04:52:34.031 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:34.031 if best_ratio < cutoff:
2025-07-02 04:52:34.031 # no non-identical "pretty close" pair
2025-07-02 04:52:34.031 if eqi is None:
2025-07-02 04:52:34.031 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:34.032 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.032 return
2025-07-02 04:52:34.032 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:34.032 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:34.032 else:
2025-07-02 04:52:34.032 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:34.032 eqi = None
2025-07-02 04:52:34.032
2025-07-02 04:52:34.032 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:34.032 # identical
2025-07-02 04:52:34.032
2025-07-02 04:52:34.032 # pump out diffs from before the synch point
2025-07-02 04:52:34.032 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:34.032
2025-07-02 04:52:34.032 # do intraline marking on the synch pair
2025-07-02 04:52:34.032 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:34.032 if eqi is None:
2025-07-02 04:52:34.032 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:34.032 atags = btags = ""
2025-07-02 04:52:34.032 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:34.032 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:34.033 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:34.033 if tag == 'replace':
2025-07-02 04:52:34.033 atags += '^' * la
2025-07-02 04:52:34.033 btags += '^' * lb
2025-07-02 04:52:34.033 elif tag == 'delete':
2025-07-02 04:52:34.033 atags += '-' * la
2025-07-02 04:52:34.033 elif tag == 'insert':
2025-07-02 04:52:34.033 btags += '+' * lb
2025-07-02 04:52:34.033 elif tag == 'equal':
2025-07-02 04:52:34.033 atags += ' ' * la
2025-07-02 04:52:34.033 btags += ' ' * lb
2025-07-02 04:52:34.033 else:
2025-07-02 04:52:34.033 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:34.033 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:34.033 else:
2025-07-02 04:52:34.033 # the synch pair is identical
2025-07-02 04:52:34.033 yield ' ' + aelt
2025-07-02 04:52:34.033
2025-07-02 04:52:34.033 # pump out diffs from after the synch point
2025-07-02 04:52:34.033 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:34.033
2025-07-02 04:52:34.033 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:34.034 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.034
2025-07-02 04:52:34.034 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.034 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.034 alo = 516, ahi = 1101
2025-07-02 04:52:34.034 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.034 blo = 516, bhi = 1101
2025-07-02 04:52:34.034
2025-07-02 04:52:34.034 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.034 g = []
2025-07-02 04:52:34.034 if alo < ahi:
2025-07-02 04:52:34.034 if blo < bhi:
2025-07-02 04:52:34.034 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.034 else:
2025-07-02 04:52:34.034 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:34.034 elif blo < bhi:
2025-07-02 04:52:34.034 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:34.034
2025-07-02 04:52:34.034 > yield from g
2025-07-02 04:52:34.034
2025-07-02 04:52:34.034 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:34.035 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.035
2025-07-02 04:52:34.035 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.035 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.035 alo = 516, ahi = 1101
2025-07-02 04:52:34.035 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.035 blo = 516, bhi = 1101
2025-07-02 04:52:34.035
2025-07-02 04:52:34.035 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.035 r"""
2025-07-02 04:52:34.035 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:34.035 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:34.035 synch point, and intraline difference marking is done on the
2025-07-02 04:52:34.035 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:34.035
2025-07-02 04:52:34.035 Example:
2025-07-02 04:52:34.035
2025-07-02 04:52:34.035 >>> d = Differ()
2025-07-02 04:52:34.035 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:34.035 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:34.035 >>> print(''.join(results), end="")
2025-07-02 04:52:34.036 - abcDefghiJkl
2025-07-02 04:52:34.036 + abcdefGhijkl
2025-07-02 04:52:34.036 """
2025-07-02 04:52:34.036
2025-07-02 04:52:34.036 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:34.036 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:34.036 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:34.036 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:34.036 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:34.036
2025-07-02 04:52:34.036 # search for the pair that matches best without being identical
2025-07-02 04:52:34.036 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:34.036 # on junk -- unless we have to)
2025-07-02 04:52:34.036 for j in range(blo, bhi):
2025-07-02 04:52:34.036 bj = b[j]
2025-07-02 04:52:34.036 cruncher.set_seq2(bj)
2025-07-02 04:52:34.036 for i in range(alo, ahi):
2025-07-02 04:52:34.036 ai = a[i]
2025-07-02 04:52:34.036 if ai == bj:
2025-07-02 04:52:34.036 if eqi is None:
2025-07-02 04:52:34.037 eqi, eqj = i, j
2025-07-02 04:52:34.037 continue
2025-07-02 04:52:34.037 cruncher.set_seq1(ai)
2025-07-02 04:52:34.037 # computing similarity is expensive, so use the quick
2025-07-02 04:52:34.037 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:34.037 # compares by a factor of 3.
2025-07-02 04:52:34.037 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:34.037 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:34.037 # of the computation is cached by cruncher
2025-07-02 04:52:34.037 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:34.037 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:34.037 cruncher.ratio() > best_ratio:
2025-07-02 04:52:34.037 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:34.037 if best_ratio < cutoff:
2025-07-02 04:52:34.037 # no non-identical "pretty close" pair
2025-07-02 04:52:34.037 if eqi is None:
2025-07-02 04:52:34.037 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:34.037 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.037 return
2025-07-02 04:52:34.037 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:34.038 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:34.038 else:
2025-07-02 04:52:34.038 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:34.038 eqi = None
2025-07-02 04:52:34.038
2025-07-02 04:52:34.038 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:34.038 # identical
2025-07-02 04:52:34.038
2025-07-02 04:52:34.038 # pump out diffs from before the synch point
2025-07-02 04:52:34.038 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:34.038
2025-07-02 04:52:34.038 # do intraline marking on the synch pair
2025-07-02 04:52:34.038 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:34.038 if eqi is None:
2025-07-02 04:52:34.038 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:34.038 atags = btags = ""
2025-07-02 04:52:34.038 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:34.038 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:34.038 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:34.038 if tag == 'replace':
2025-07-02 04:52:34.039 atags += '^' * la
2025-07-02 04:52:34.039 btags += '^' * lb
2025-07-02 04:52:34.039 elif tag == 'delete':
2025-07-02 04:52:34.039 atags += '-' * la
2025-07-02 04:52:34.039 elif tag == 'insert':
2025-07-02 04:52:34.039 btags += '+' * lb
2025-07-02 04:52:34.039 elif tag == 'equal':
2025-07-02 04:52:34.039 atags += ' ' * la
2025-07-02 04:52:34.039 btags += ' ' * lb
2025-07-02 04:52:34.039 else:
2025-07-02 04:52:34.039 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:34.039 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:34.039 else:
2025-07-02 04:52:34.039 # the synch pair is identical
2025-07-02 04:52:34.039 yield ' ' + aelt
2025-07-02 04:52:34.039
2025-07-02 04:52:34.039 # pump out diffs from after the synch point
2025-07-02 04:52:34.039 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:34.039
2025-07-02 04:52:34.039 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:34.039 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.040
2025-07-02 04:52:34.040 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.040 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.040 alo = 517, ahi = 1101
2025-07-02 04:52:34.040 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.040 blo = 517, bhi = 1101
2025-07-02 04:52:34.040
2025-07-02 04:52:34.040 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.040 g = []
2025-07-02 04:52:34.040 if alo < ahi:
2025-07-02 04:52:34.040 if blo < bhi:
2025-07-02 04:52:34.040 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.040 else:
2025-07-02 04:52:34.040 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:34.040 elif blo < bhi:
2025-07-02 04:52:34.040 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:34.040
2025-07-02 04:52:34.040 > yield from g
2025-07-02 04:52:34.040
2025-07-02 04:52:34.040 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:34.040 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.040
2025-07-02 04:52:34.041 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.041 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.041 alo = 517, ahi = 1101
2025-07-02 04:52:34.041 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.041 blo = 517, bhi = 1101
2025-07-02 04:52:34.041
2025-07-02 04:52:34.041 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.041 r"""
2025-07-02 04:52:34.041 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:34.041 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:34.041 synch point, and intraline difference marking is done on the
2025-07-02 04:52:34.041 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:34.041
2025-07-02 04:52:34.041 Example:
2025-07-02 04:52:34.041
2025-07-02 04:52:34.041 >>> d = Differ()
2025-07-02 04:52:34.041 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:34.041 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:34.041 >>> print(''.join(results), end="")
2025-07-02 04:52:34.041 - abcDefghiJkl
2025-07-02 04:52:34.042 + abcdefGhijkl
2025-07-02 04:52:34.042 """
2025-07-02 04:52:34.042
2025-07-02 04:52:34.042 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:34.042 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:34.042 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:34.042 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:34.042 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:34.042
2025-07-02 04:52:34.042 # search for the pair that matches best without being identical
2025-07-02 04:52:34.042 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:34.042 # on junk -- unless we have to)
2025-07-02 04:52:34.042 for j in range(blo, bhi):
2025-07-02 04:52:34.042 bj = b[j]
2025-07-02 04:52:34.042 cruncher.set_seq2(bj)
2025-07-02 04:52:34.042 for i in range(alo, ahi):
2025-07-02 04:52:34.042 ai = a[i]
2025-07-02 04:52:34.042 if ai == bj:
2025-07-02 04:52:34.042 if eqi is None:
2025-07-02 04:52:34.043 eqi, eqj = i, j
2025-07-02 04:52:34.043 continue
2025-07-02 04:52:34.043 cruncher.set_seq1(ai)
2025-07-02 04:52:34.043 # computing similarity is expensive, so use the quick
2025-07-02 04:52:34.043 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:34.043 # compares by a factor of 3.
2025-07-02 04:52:34.043 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:34.043 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:34.043 # of the computation is cached by cruncher
2025-07-02 04:52:34.043 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:34.043 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:34.043 cruncher.ratio() > best_ratio:
2025-07-02 04:52:34.043 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:34.043 if best_ratio < cutoff:
2025-07-02 04:52:34.043 # no non-identical "pretty close" pair
2025-07-02 04:52:34.043 if eqi is None:
2025-07-02 04:52:34.043 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:34.043 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.043 return
2025-07-02 04:52:34.043 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:34.043 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:34.044 else:
2025-07-02 04:52:34.044 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:34.044 eqi = None
2025-07-02 04:52:34.044
2025-07-02 04:52:34.044 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:34.044 # identical
2025-07-02 04:52:34.044
2025-07-02 04:52:34.044 # pump out diffs from before the synch point
2025-07-02 04:52:34.044 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:34.044
2025-07-02 04:52:34.044 # do intraline marking on the synch pair
2025-07-02 04:52:34.044 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:34.044 if eqi is None:
2025-07-02 04:52:34.044 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:34.044 atags = btags = ""
2025-07-02 04:52:34.044 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:34.044 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:34.044 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:34.044 if tag == 'replace':
2025-07-02 04:52:34.044 atags += '^' * la
2025-07-02 04:52:34.044 btags += '^' * lb
2025-07-02 04:52:34.045 elif tag == 'delete':
2025-07-02 04:52:34.045 atags += '-' * la
2025-07-02 04:52:34.045 elif tag == 'insert':
2025-07-02 04:52:34.045 btags += '+' * lb
2025-07-02 04:52:34.045 elif tag == 'equal':
2025-07-02 04:52:34.045 atags += ' ' * la
2025-07-02 04:52:34.045 btags += ' ' * lb
2025-07-02 04:52:34.045 else:
2025-07-02 04:52:34.045 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:34.045 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:34.045 else:
2025-07-02 04:52:34.045 # the synch pair is identical
2025-07-02 04:52:34.045 yield ' ' + aelt
2025-07-02 04:52:34.045
2025-07-02 04:52:34.045 # pump out diffs from after the synch point
2025-07-02 04:52:34.045 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:34.045
2025-07-02 04:52:34.045 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:34.045 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.045
2025-07-02 04:52:34.045 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.045 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.046 alo = 518, ahi = 1101
2025-07-02 04:52:34.046 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.046 blo = 518, bhi = 1101
2025-07-02 04:52:34.046
2025-07-02 04:52:34.046 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.046 g = []
2025-07-02 04:52:34.046 if alo < ahi:
2025-07-02 04:52:34.046 if blo < bhi:
2025-07-02 04:52:34.046 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.046 else:
2025-07-02 04:52:34.046 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:34.046 elif blo < bhi:
2025-07-02 04:52:34.046 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:34.046
2025-07-02 04:52:34.046 > yield from g
2025-07-02 04:52:34.046
2025-07-02 04:52:34.046 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:34.046 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.047
2025-07-02 04:52:34.047 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.047 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.047 alo = 518, ahi = 1101
2025-07-02 04:52:34.047 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.047 blo = 518, bhi = 1101
2025-07-02 04:52:34.047
2025-07-02 04:52:34.047 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.047 r"""
2025-07-02 04:52:34.047 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:34.047 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:34.047 synch point, and intraline difference marking is done on the
2025-07-02 04:52:34.047 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:34.047
2025-07-02 04:52:34.047 Example:
2025-07-02 04:52:34.047
2025-07-02 04:52:34.047 >>> d = Differ()
2025-07-02 04:52:34.047 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:34.047 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:34.047 >>> print(''.join(results), end="")
2025-07-02 04:52:34.047 - abcDefghiJkl
2025-07-02 04:52:34.048 + abcdefGhijkl
2025-07-02 04:52:34.048 """
2025-07-02 04:52:34.048
2025-07-02 04:52:34.048 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:34.048 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:34.048 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:34.048 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:34.048 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:34.048
2025-07-02 04:52:34.048 # search for the pair that matches best without being identical
2025-07-02 04:52:34.048 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:34.048 # on junk -- unless we have to)
2025-07-02 04:52:34.048 for j in range(blo, bhi):
2025-07-02 04:52:34.048 bj = b[j]
2025-07-02 04:52:34.048 cruncher.set_seq2(bj)
2025-07-02 04:52:34.048 for i in range(alo, ahi):
2025-07-02 04:52:34.048 ai = a[i]
2025-07-02 04:52:34.048 if ai == bj:
2025-07-02 04:52:34.048 if eqi is None:
2025-07-02 04:52:34.049 eqi, eqj = i, j
2025-07-02 04:52:34.049 continue
2025-07-02 04:52:34.049 cruncher.set_seq1(ai)
2025-07-02 04:52:34.049 # computing similarity is expensive, so use the quick
2025-07-02 04:52:34.049 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:34.049 # compares by a factor of 3.
2025-07-02 04:52:34.049 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:34.049 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:34.049 # of the computation is cached by cruncher
2025-07-02 04:52:34.049 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:34.049 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:34.049 cruncher.ratio() > best_ratio:
2025-07-02 04:52:34.049 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:34.049 if best_ratio < cutoff:
2025-07-02 04:52:34.049 # no non-identical "pretty close" pair
2025-07-02 04:52:34.049 if eqi is None:
2025-07-02 04:52:34.049 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:34.049 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.049 return
2025-07-02 04:52:34.049 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:34.049 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:34.049 else:
2025-07-02 04:52:34.050 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:34.050 eqi = None
2025-07-02 04:52:34.050
2025-07-02 04:52:34.050 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:34.050 # identical
2025-07-02 04:52:34.050
2025-07-02 04:52:34.050 # pump out diffs from before the synch point
2025-07-02 04:52:34.050 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:34.050
2025-07-02 04:52:34.050 # do intraline marking on the synch pair
2025-07-02 04:52:34.050 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:34.050 if eqi is None:
2025-07-02 04:52:34.050 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:34.050 atags = btags = ""
2025-07-02 04:52:34.050 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:34.050 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:34.050 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:34.050 if tag == 'replace':
2025-07-02 04:52:34.050 atags += '^' * la
2025-07-02 04:52:34.050 btags += '^' * lb
2025-07-02 04:52:34.050 elif tag == 'delete':
2025-07-02 04:52:34.051 atags += '-' * la
2025-07-02 04:52:34.051 elif tag == 'insert':
2025-07-02 04:52:34.051 btags += '+' * lb
2025-07-02 04:52:34.051 elif tag == 'equal':
2025-07-02 04:52:34.051 atags += ' ' * la
2025-07-02 04:52:34.051 btags += ' ' * lb
2025-07-02 04:52:34.051 else:
2025-07-02 04:52:34.051 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:34.051 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:34.051 else:
2025-07-02 04:52:34.051 # the synch pair is identical
2025-07-02 04:52:34.051 yield ' ' + aelt
2025-07-02 04:52:34.051
2025-07-02 04:52:34.051 # pump out diffs from after the synch point
2025-07-02 04:52:34.051 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:34.051
2025-07-02 04:52:34.051 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:34.051 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.051
2025-07-02 04:52:34.051 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.051 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.051 alo = 519, ahi = 1101
2025-07-02 04:52:34.052 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.052 blo = 519, bhi = 1101
2025-07-02 04:52:34.052
2025-07-02 04:52:34.052 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.052 g = []
2025-07-02 04:52:34.052 if alo < ahi:
2025-07-02 04:52:34.052 if blo < bhi:
2025-07-02 04:52:34.052 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.052 else:
2025-07-02 04:52:34.052 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:34.052 elif blo < bhi:
2025-07-02 04:52:34.052 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:34.052
2025-07-02 04:52:34.052 > yield from g
2025-07-02 04:52:34.052
2025-07-02 04:52:34.052 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:34.052 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.052
2025-07-02 04:52:34.052 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.052 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.052 alo = 519, ahi = 1101
2025-07-02 04:52:34.053 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.053 blo = 519, bhi = 1101
2025-07-02 04:52:34.053
2025-07-02 04:52:34.053 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.053 r"""
2025-07-02 04:52:34.053 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:34.053 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:34.053 synch point, and intraline difference marking is done on the
2025-07-02 04:52:34.053 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:34.053
2025-07-02 04:52:34.053 Example:
2025-07-02 04:52:34.053
2025-07-02 04:52:34.053 >>> d = Differ()
2025-07-02 04:52:34.053 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:34.053 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:34.053 >>> print(''.join(results), end="")
2025-07-02 04:52:34.053 - abcDefghiJkl
2025-07-02 04:52:34.053 + abcdefGhijkl
2025-07-02 04:52:34.053 """
2025-07-02 04:52:34.054
2025-07-02 04:52:34.054 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:34.054 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:34.054 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:34.054 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:34.054 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:34.054
2025-07-02 04:52:34.054 # search for the pair that matches best without being identical
2025-07-02 04:52:34.054 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:34.054 # on junk -- unless we have to)
2025-07-02 04:52:34.054 for j in range(blo, bhi):
2025-07-02 04:52:34.054 bj = b[j]
2025-07-02 04:52:34.054 cruncher.set_seq2(bj)
2025-07-02 04:52:34.054 for i in range(alo, ahi):
2025-07-02 04:52:34.054 ai = a[i]
2025-07-02 04:52:34.054 if ai == bj:
2025-07-02 04:52:34.054 if eqi is None:
2025-07-02 04:52:34.054 eqi, eqj = i, j
2025-07-02 04:52:34.054 continue
2025-07-02 04:52:34.054 cruncher.set_seq1(ai)
2025-07-02 04:52:34.055 # computing similarity is expensive, so use the quick
2025-07-02 04:52:34.055 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:34.055 # compares by a factor of 3.
2025-07-02 04:52:34.055 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:34.055 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:34.055 # of the computation is cached by cruncher
2025-07-02 04:52:34.055 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:34.055 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:34.055 cruncher.ratio() > best_ratio:
2025-07-02 04:52:34.055 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:34.055 if best_ratio < cutoff:
2025-07-02 04:52:34.055 # no non-identical "pretty close" pair
2025-07-02 04:52:34.055 if eqi is None:
2025-07-02 04:52:34.055 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:34.055 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.055 return
2025-07-02 04:52:34.055 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:34.055 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:34.055 else:
2025-07-02 04:52:34.055 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:34.056 eqi = None
2025-07-02 04:52:34.056
2025-07-02 04:52:34.056 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:34.056 # identical
2025-07-02 04:52:34.056
2025-07-02 04:52:34.056 # pump out diffs from before the synch point
2025-07-02 04:52:34.056 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:34.056
2025-07-02 04:52:34.056 # do intraline marking on the synch pair
2025-07-02 04:52:34.056 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:34.056 if eqi is None:
2025-07-02 04:52:34.056 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:34.056 atags = btags = ""
2025-07-02 04:52:34.056 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:34.056 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:34.056 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:34.056 if tag == 'replace':
2025-07-02 04:52:34.056 atags += '^' * la
2025-07-02 04:52:34.056 btags += '^' * lb
2025-07-02 04:52:34.056 elif tag == 'delete':
2025-07-02 04:52:34.056 atags += '-' * la
2025-07-02 04:52:34.057 elif tag == 'insert':
2025-07-02 04:52:34.057 btags += '+' * lb
2025-07-02 04:52:34.057 elif tag == 'equal':
2025-07-02 04:52:34.057 atags += ' ' * la
2025-07-02 04:52:34.057 btags += ' ' * lb
2025-07-02 04:52:34.057 else:
2025-07-02 04:52:34.057 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:34.057 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:34.057 else:
2025-07-02 04:52:34.057 # the synch pair is identical
2025-07-02 04:52:34.057 yield ' ' + aelt
2025-07-02 04:52:34.057
2025-07-02 04:52:34.057 # pump out diffs from after the synch point
2025-07-02 04:52:34.057 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:34.057
2025-07-02 04:52:34.057 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:34.057 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.057
2025-07-02 04:52:34.057 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.057 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.058 alo = 520, ahi = 1101
2025-07-02 04:52:34.058 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.058 blo = 520, bhi = 1101
2025-07-02 04:52:34.058
2025-07-02 04:52:34.058 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.058 g = []
2025-07-02 04:52:34.058 if alo < ahi:
2025-07-02 04:52:34.058 if blo < bhi:
2025-07-02 04:52:34.058 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.058 else:
2025-07-02 04:52:34.058 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:34.058 elif blo < bhi:
2025-07-02 04:52:34.058 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:34.058
2025-07-02 04:52:34.058 > yield from g
2025-07-02 04:52:34.058
2025-07-02 04:52:34.058 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:34.058 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.058
2025-07-02 04:52:34.058 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.058 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.059 alo = 520, ahi = 1101
2025-07-02 04:52:34.059 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.059 blo = 520, bhi = 1101
2025-07-02 04:52:34.059
2025-07-02 04:52:34.059 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.059 r"""
2025-07-02 04:52:34.059 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:34.059 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:34.059 synch point, and intraline difference marking is done on the
2025-07-02 04:52:34.059 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:34.059
2025-07-02 04:52:34.059 Example:
2025-07-02 04:52:34.059
2025-07-02 04:52:34.059 >>> d = Differ()
2025-07-02 04:52:34.059 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:34.059 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:34.059 >>> print(''.join(results), end="")
2025-07-02 04:52:34.059 - abcDefghiJkl
2025-07-02 04:52:34.059 + abcdefGhijkl
2025-07-02 04:52:34.060 """
2025-07-02 04:52:34.060
2025-07-02 04:52:34.060 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:34.060 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:34.060 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:34.060 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:34.060 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:34.060
2025-07-02 04:52:34.060 # search for the pair that matches best without being identical
2025-07-02 04:52:34.060 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:34.060 # on junk -- unless we have to)
2025-07-02 04:52:34.060 for j in range(blo, bhi):
2025-07-02 04:52:34.060 bj = b[j]
2025-07-02 04:52:34.060 cruncher.set_seq2(bj)
2025-07-02 04:52:34.060 for i in range(alo, ahi):
2025-07-02 04:52:34.060 ai = a[i]
2025-07-02 04:52:34.060 if ai == bj:
2025-07-02 04:52:34.060 if eqi is None:
2025-07-02 04:52:34.060 eqi, eqj = i, j
2025-07-02 04:52:34.060 continue
2025-07-02 04:52:34.060 cruncher.set_seq1(ai)
2025-07-02 04:52:34.061 # computing similarity is expensive, so use the quick
2025-07-02 04:52:34.061 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:34.061 # compares by a factor of 3.
2025-07-02 04:52:34.061 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:34.061 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:34.061 # of the computation is cached by cruncher
2025-07-02 04:52:34.061 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:34.061 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:34.061 cruncher.ratio() > best_ratio:
2025-07-02 04:52:34.061 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:34.061 if best_ratio < cutoff:
2025-07-02 04:52:34.061 # no non-identical "pretty close" pair
2025-07-02 04:52:34.061 if eqi is None:
2025-07-02 04:52:34.061 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:34.061 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.061 return
2025-07-02 04:52:34.061 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:34.061 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:34.061 else:
2025-07-02 04:52:34.062 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:34.062 eqi = None
2025-07-02 04:52:34.062
2025-07-02 04:52:34.062 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:34.062 # identical
2025-07-02 04:52:34.062
2025-07-02 04:52:34.062 # pump out diffs from before the synch point
2025-07-02 04:52:34.062 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:34.062
2025-07-02 04:52:34.062 # do intraline marking on the synch pair
2025-07-02 04:52:34.062 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:34.062 if eqi is None:
2025-07-02 04:52:34.062 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:34.062 atags = btags = ""
2025-07-02 04:52:34.062 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:34.062 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:34.062 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:34.062 if tag == 'replace':
2025-07-02 04:52:34.062 atags += '^' * la
2025-07-02 04:52:34.062 btags += '^' * lb
2025-07-02 04:52:34.063 elif tag == 'delete':
2025-07-02 04:52:34.063 atags += '-' * la
2025-07-02 04:52:34.063 elif tag == 'insert':
2025-07-02 04:52:34.063 btags += '+' * lb
2025-07-02 04:52:34.063 elif tag == 'equal':
2025-07-02 04:52:34.063 atags += ' ' * la
2025-07-02 04:52:34.063 btags += ' ' * lb
2025-07-02 04:52:34.063 else:
2025-07-02 04:52:34.063 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:34.063 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:34.063 else:
2025-07-02 04:52:34.063 # the synch pair is identical
2025-07-02 04:52:34.063 yield ' ' + aelt
2025-07-02 04:52:34.063
2025-07-02 04:52:34.063 # pump out diffs from after the synch point
2025-07-02 04:52:34.063 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:34.063
2025-07-02 04:52:34.063 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:34.063 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.063
2025-07-02 04:52:34.063 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.064 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.064 alo = 521, ahi = 1101
2025-07-02 04:52:34.064 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.064 blo = 521, bhi = 1101
2025-07-02 04:52:34.064
2025-07-02 04:52:34.064 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.064 g = []
2025-07-02 04:52:34.064 if alo < ahi:
2025-07-02 04:52:34.064 if blo < bhi:
2025-07-02 04:52:34.064 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.064 else:
2025-07-02 04:52:34.064 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:34.064 elif blo < bhi:
2025-07-02 04:52:34.064 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:34.064
2025-07-02 04:52:34.064 > yield from g
2025-07-02 04:52:34.064
2025-07-02 04:52:34.064 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:34.064 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.064
2025-07-02 04:52:34.065 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.065 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.065 alo = 521, ahi = 1101
2025-07-02 04:52:34.065 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.065 blo = 521, bhi = 1101
2025-07-02 04:52:34.065
2025-07-02 04:52:34.065 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.065 r"""
2025-07-02 04:52:34.065 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:34.065 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:34.065 synch point, and intraline difference marking is done on the
2025-07-02 04:52:34.065 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:34.065
2025-07-02 04:52:34.065 Example:
2025-07-02 04:52:34.065
2025-07-02 04:52:34.065 >>> d = Differ()
2025-07-02 04:52:34.065 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:34.065 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:34.065 >>> print(''.join(results), end="")
2025-07-02 04:52:34.065 - abcDefghiJkl
2025-07-02 04:52:34.066 + abcdefGhijkl
2025-07-02 04:52:34.066 """
2025-07-02 04:52:34.066
2025-07-02 04:52:34.066 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:34.066 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:34.066 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:34.066 cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:34.066 eqi, eqj = None, None # 1st indices of equal lines (if any)
2025-07-02 04:52:34.066
2025-07-02 04:52:34.066 # search for the pair that matches best without being identical
2025-07-02 04:52:34.066 # (identical lines must be junk lines, & we don't want to synch up
2025-07-02 04:52:34.066 # on junk -- unless we have to)
2025-07-02 04:52:34.066 for j in range(blo, bhi):
2025-07-02 04:52:34.066 bj = b[j]
2025-07-02 04:52:34.066 cruncher.set_seq2(bj)
2025-07-02 04:52:34.066 for i in range(alo, ahi):
2025-07-02 04:52:34.066 ai = a[i]
2025-07-02 04:52:34.066 if ai == bj:
2025-07-02 04:52:34.066 if eqi is None:
2025-07-02 04:52:34.067 eqi, eqj = i, j
2025-07-02 04:52:34.067 continue
2025-07-02 04:52:34.067 cruncher.set_seq1(ai)
2025-07-02 04:52:34.067 # computing similarity is expensive, so use the quick
2025-07-02 04:52:34.067 # upper bounds first -- have seen this speed up messy
2025-07-02 04:52:34.067 # compares by a factor of 3.
2025-07-02 04:52:34.067 # note that ratio() is only expensive to compute the first
2025-07-02 04:52:34.067 # time it's called on a sequence pair; the expensive part
2025-07-02 04:52:34.067 # of the computation is cached by cruncher
2025-07-02 04:52:34.067 if cruncher.real_quick_ratio() > best_ratio and \
2025-07-02 04:52:34.067 cruncher.quick_ratio() > best_ratio and \
2025-07-02 04:52:34.067 cruncher.ratio() > best_ratio:
2025-07-02 04:52:34.067 best_ratio, best_i, best_j = cruncher.ratio(), i, j
2025-07-02 04:52:34.067 if best_ratio < cutoff:
2025-07-02 04:52:34.067 # no non-identical "pretty close" pair
2025-07-02 04:52:34.067 if eqi is None:
2025-07-02 04:52:34.067 # no identical pair either -- treat it as a straight replace
2025-07-02 04:52:34.067 yield from self._plain_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.067 return
2025-07-02 04:52:34.067 # no close pair, but an identical pair -- synch up on that
2025-07-02 04:52:34.068 best_i, best_j, best_ratio = eqi, eqj, 1.0
2025-07-02 04:52:34.068 else:
2025-07-02 04:52:34.068 # there's a close pair, so forget the identical pair (if any)
2025-07-02 04:52:34.068 eqi = None
2025-07-02 04:52:34.068
2025-07-02 04:52:34.068 # a[best_i] very similar to b[best_j]; eqi is None iff they're not
2025-07-02 04:52:34.068 # identical
2025-07-02 04:52:34.068
2025-07-02 04:52:34.068 # pump out diffs from before the synch point
2025-07-02 04:52:34.068 yield from self._fancy_helper(a, alo, best_i, b, blo, best_j)
2025-07-02 04:52:34.068
2025-07-02 04:52:34.068 # do intraline marking on the synch pair
2025-07-02 04:52:34.068 aelt, belt = a[best_i], b[best_j]
2025-07-02 04:52:34.068 if eqi is None:
2025-07-02 04:52:34.068 # pump out a '-', '?', '+', '?' quad for the synched lines
2025-07-02 04:52:34.068 atags = btags = ""
2025-07-02 04:52:34.068 cruncher.set_seqs(aelt, belt)
2025-07-02 04:52:34.068 for tag, ai1, ai2, bj1, bj2 in cruncher.get_opcodes():
2025-07-02 04:52:34.068 la, lb = ai2 - ai1, bj2 - bj1
2025-07-02 04:52:34.068 if tag == 'replace':
2025-07-02 04:52:34.068 atags += '^' * la
2025-07-02 04:52:34.069 btags += '^' * lb
2025-07-02 04:52:34.069 elif tag == 'delete':
2025-07-02 04:52:34.069 atags += '-' * la
2025-07-02 04:52:34.069 elif tag == 'insert':
2025-07-02 04:52:34.069 btags += '+' * lb
2025-07-02 04:52:34.069 elif tag == 'equal':
2025-07-02 04:52:34.069 atags += ' ' * la
2025-07-02 04:52:34.069 btags += ' ' * lb
2025-07-02 04:52:34.069 else:
2025-07-02 04:52:34.069 raise ValueError('unknown tag %r' % (tag,))
2025-07-02 04:52:34.069 yield from self._qformat(aelt, belt, atags, btags)
2025-07-02 04:52:34.069 else:
2025-07-02 04:52:34.069 # the synch pair is identical
2025-07-02 04:52:34.069 yield ' ' + aelt
2025-07-02 04:52:34.069
2025-07-02 04:52:34.069 # pump out diffs from after the synch point
2025-07-02 04:52:34.069 > yield from self._fancy_helper(a, best_i+1, ahi, b, best_j+1, bhi)
2025-07-02 04:52:34.069
2025-07-02 04:52:34.069 C:\Python3x\Lib\difflib.py:985:
2025-07-02 04:52:34.069 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.069
2025-07-02 04:52:34.070 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.070 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.070 alo = 522, ahi = 1101
2025-07-02 04:52:34.070 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.070 blo = 522, bhi = 1101
2025-07-02 04:52:34.070
2025-07-02 04:52:34.070 def _fancy_helper(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.070 g = []
2025-07-02 04:52:34.070 if alo < ahi:
2025-07-02 04:52:34.070 if blo < bhi:
2025-07-02 04:52:34.070 g = self._fancy_replace(a, alo, ahi, b, blo, bhi)
2025-07-02 04:52:34.070 else:
2025-07-02 04:52:34.070 g = self._dump('-', a, alo, ahi)
2025-07-02 04:52:34.070 elif blo < bhi:
2025-07-02 04:52:34.070 g = self._dump('+', b, blo, bhi)
2025-07-02 04:52:34.070
2025-07-02 04:52:34.070 > yield from g
2025-07-02 04:52:34.070
2025-07-02 04:52:34.070 C:\Python3x\Lib\difflib.py:997:
2025-07-02 04:52:34.070 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.070
2025-07-02 04:52:34.070 self = <difflib.Differ object at [hex]>
2025-07-02 04:52:34.071 a = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...r_0 yyy', '1 var_1 yyy', '1 var_2 yyy', ...]
2025-07-02 04:52:34.071 alo = 522, ahi = 1101
2025-07-02 04:52:34.071 b = ['', 'WAS_OVERWRITTEN CTX_KEY CTX_VAL', '=============== ============================== =======...var_0 yyy', '1var_1 yyy', '1var_2 yyy', ...]
2025-07-02 04:52:34.071 blo = 522, bhi = 1101
2025-07-02 04:52:34.071
2025-07-02 04:52:34.071 def _fancy_replace(self, a, alo, ahi, b, blo, bhi):
2025-07-02 04:52:34.071 r"""
2025-07-02 04:52:34.071 When replacing one block of lines with another, search the blocks
2025-07-02 04:52:34.071 for *similar* lines; the best-matching pair (if any) is used as a
2025-07-02 04:52:34.071 synch point, and intraline difference marking is done on the
2025-07-02 04:52:34.071 similar pair. Lots of work, but often worth it.
2025-07-02 04:52:34.071
2025-07-02 04:52:34.071 Example:
2025-07-02 04:52:34.071
2025-07-02 04:52:34.071 >>> d = Differ()
2025-07-02 04:52:34.071 >>> results = d._fancy_replace(['abcDefghiJkl\n'], 0, 1,
2025-07-02 04:52:34.071 ... ['abcdefGhijkl\n'], 0, 1)
2025-07-02 04:52:34.071 >>> print(''.join(results), end="")
2025-07-02 04:52:34.071 - abcDefghiJkl
2025-07-02 04:52:34.072 + abcdefGhijkl
2025-07-02 04:52:34.072 """
2025-07-02 04:52:34.072
2025-07-02 04:52:34.072 # don't synch up unless the lines have a similarity score of at
2025-07-02 04:52:34.072 # least cutoff; best_ratio tracks the best score seen so far
2025-07-02 04:52:34.072 best_ratio, cutoff = 0.74, 0.75
2025-07-02 04:52:34.072 > cruncher = SequenceMatcher(self.charjunk)
2025-07-02 04:52:34.072
2025-07-02 04:52:34.072 C:\Python3x\Lib\difflib.py:915:
2025-07-02 04:52:34.072 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.072
2025-07-02 04:52:34.072 self = <difflib.SequenceMatcher object at [hex]>
2025-07-02 04:52:34.072 isjunk = <function IS_CHARACTER_JUNK at 0x0000025DB66BDC60>, a = '', b = ''
2025-07-02 04:52:34.072 autojunk = True
2025-07-02 04:52:34.072
2025-07-02 04:52:34.072 def __init__(self, isjunk=None, a='', b='', autojunk=True):
2025-07-02 04:52:34.072 """Construct a SequenceMatcher.
2025-07-02 04:52:34.072
2025-07-02 04:52:34.072 Optional arg isjunk is None (the default), or a one-argument
2025-07-02 04:52:34.073 function that takes a sequence element and returns true iff the
2025-07-02 04:52:34.073 element is junk. None is equivalent to passing "lambda x: 0", i.e.
2025-07-02 04:52:34.073 no elements are considered to be junk. For example, pass
2025-07-02 04:52:34.073 lambda x: x in " \\t"
2025-07-02 04:52:34.073 if you're comparing lines as sequences of characters, and don't
2025-07-02 04:52:34.073 want to synch up on blanks or hard tabs.
2025-07-02 04:52:34.073
2025-07-02 04:52:34.073 Optional arg a is the first of two sequences to be compared. By
2025-07-02 04:52:34.073 default, an empty string. The elements of a must be hashable. See
2025-07-02 04:52:34.073 also .set_seqs() and .set_seq1().
2025-07-02 04:52:34.073
2025-07-02 04:52:34.073 Optional arg b is the second of two sequences to be compared. By
2025-07-02 04:52:34.073 default, an empty string. The elements of b must be hashable. See
2025-07-02 04:52:34.073 also .set_seqs() and .set_seq2().
2025-07-02 04:52:34.073
2025-07-02 04:52:34.073 Optional arg autojunk should be set to False to disable the
2025-07-02 04:52:34.073 "automatic junk heuristic" that treats popular elements as junk
2025-07-02 04:52:34.073 (see module documentation for more information).
2025-07-02 04:52:34.073 """
2025-07-02 04:52:34.073
2025-07-02 04:52:34.074 # Members:
2025-07-02 04:52:34.074 # a
2025-07-02 04:52:34.074 # first sequence
2025-07-02 04:52:34.074 # b
2025-07-02 04:52:34.074 # second sequence; differences are computed as "what do
2025-07-02 04:52:34.074 # we need to do to 'a' to change it into 'b'?"
2025-07-02 04:52:34.074 # b2j
2025-07-02 04:52:34.074 # for x in b, b2j[x] is a list of the indices (into b)
2025-07-02 04:52:34.074 # at which x appears; junk and popular elements do not appear
2025-07-02 04:52:34.074 # fullbcount
2025-07-02 04:52:34.074 # for x in b, fullbcount[x] == the number of times x
2025-07-02 04:52:34.074 # appears in b; only materialized if really needed (used
2025-07-02 04:52:34.074 # only for computing quick_ratio())
2025-07-02 04:52:34.074 # matching_blocks
2025-07-02 04:52:34.074 # a list of (i, j, k) triples, where a[i:i+k] == b[j:j+k];
2025-07-02 04:52:34.074 # ascending & non-overlapping in i and in j; terminated by
2025-07-02 04:52:34.074 # a dummy (len(a), len(b), 0) sentinel
2025-07-02 04:52:34.074 # opcodes
2025-07-02 04:52:34.074 # a list of (tag, i1, i2, j1, j2) tuples, where tag is
2025-07-02 04:52:34.074 # one of
2025-07-02 04:52:34.074 # 'replace' a[i1:i2] should be replaced by b[j1:j2]
2025-07-02 04:52:34.075 # 'delete' a[i1:i2] should be deleted
2025-07-02 04:52:34.075 # 'insert' b[j1:j2] should be inserted
2025-07-02 04:52:34.075 # 'equal' a[i1:i2] == b[j1:j2]
2025-07-02 04:52:34.075 # isjunk
2025-07-02 04:52:34.075 # a user-supplied function taking a sequence element and
2025-07-02 04:52:34.075 # returning true iff the element is "junk" -- this has
2025-07-02 04:52:34.075 # subtle but helpful effects on the algorithm, which I'll
2025-07-02 04:52:34.075 # get around to writing up someday <0.9 wink>.
2025-07-02 04:52:34.075 # DON'T USE! Only __chain_b uses this. Use "in self.bjunk".
2025-07-02 04:52:34.075 # bjunk
2025-07-02 04:52:34.075 # the items in b for which isjunk is True.
2025-07-02 04:52:34.075 # bpopular
2025-07-02 04:52:34.075 # nonjunk items in b treated as junk by the heuristic (if used).
2025-07-02 04:52:34.075
2025-07-02 04:52:34.075 self.isjunk = isjunk
2025-07-02 04:52:34.075 self.a = self.b = None
2025-07-02 04:52:34.075 self.autojunk = autojunk
2025-07-02 04:52:34.075 > self.set_seqs(a, b)
2025-07-02 04:52:34.075
2025-07-02 04:52:34.075 C:\Python3x\Lib\difflib.py:182:
2025-07-02 04:52:34.075 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.076
2025-07-02 04:52:34.076 self = <difflib.SequenceMatcher object at [hex]>, a = '', b = ''
2025-07-02 04:52:34.076
2025-07-02 04:52:34.076 def set_seqs(self, a, b):
2025-07-02 04:52:34.076 """Set the two sequences to be compared.
2025-07-02 04:52:34.076
2025-07-02 04:52:34.076 >>> s = SequenceMatcher()
2025-07-02 04:52:34.076 >>> s.set_seqs("abcd", "bcde")
2025-07-02 04:52:34.076 >>> s.ratio()
2025-07-02 04:52:34.076 0.75
2025-07-02 04:52:34.076 """
2025-07-02 04:52:34.076
2025-07-02 04:52:34.076 self.set_seq1(a)
2025-07-02 04:52:34.076 > self.set_seq2(b)
2025-07-02 04:52:34.076
2025-07-02 04:52:34.076 C:\Python3x\Lib\difflib.py:194:
2025-07-02 04:52:34.076 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.076
2025-07-02 04:52:34.076 self = <difflib.SequenceMatcher object at [hex]>, b = ''
2025-07-02 04:52:34.076
2025-07-02 04:52:34.076 def set_seq2(self, b):
2025-07-02 04:52:34.076 """Set the second sequence to be compared.
2025-07-02 04:52:34.077
2025-07-02 04:52:34.077 The first sequence to be compared is not changed.
2025-07-02 04:52:34.077
2025-07-02 04:52:34.077 >>> s = SequenceMatcher(None, "abcd", "bcde")
2025-07-02 04:52:34.077 >>> s.ratio()
2025-07-02 04:52:34.077 0.75
2025-07-02 04:52:34.077 >>> s.set_seq2("abcd")
2025-07-02 04:52:34.077 >>> s.ratio()
2025-07-02 04:52:34.077 1.0
2025-07-02 04:52:34.077 >>>
2025-07-02 04:52:34.077
2025-07-02 04:52:34.077 SequenceMatcher computes and caches detailed information about the
2025-07-02 04:52:34.077 second sequence, so if you want to compare one sequence S against
2025-07-02 04:52:34.077 many sequences, use .set_seq2(S) once and call .set_seq1(x)
2025-07-02 04:52:34.077 repeatedly for each of the other sequences.
2025-07-02 04:52:34.077
2025-07-02 04:52:34.077 See also set_seqs() and set_seq1().
2025-07-02 04:52:34.077 """
2025-07-02 04:52:34.078
2025-07-02 04:52:34.078 if b is self.b:
2025-07-02 04:52:34.078 return
2025-07-02 04:52:34.078 self.b = b
2025-07-02 04:52:34.078 self.matching_blocks = self.opcodes = None
2025-07-02 04:52:34.078 self.fullbcount = None
2025-07-02 04:52:34.078 > self.__chain_b()
2025-07-02 04:52:34.078
2025-07-02 04:52:34.078 C:\Python3x\Lib\difflib.py:248:
2025-07-02 04:52:34.078 _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _ _
2025-07-02 04:52:34.078
2025-07-02 04:52:34.078 self = <difflib.SequenceMatcher object at [hex]>
2025-07-02 04:52:34.078
2025-07-02 04:52:34.078 def __chain_b(self):
2025-07-02 04:52:34.078 # Because isjunk is a user-defined (not C) function, and we test
2025-07-02 04:52:34.078 # for junk a LOT, it's important to minimize the number of calls.
2025-07-02 04:52:34.078 # Before the tricks described here, __chain_b was by far the most
2025-07-02 04:52:34.078 # time-consuming routine in the whole module! If anyone sees
2025-07-02 04:52:34.078 # Jim Roskind, thank him again for profile.py -- I never would
2025-07-02 04:52:34.078 # have guessed that.
2025-07-02 04:52:34.078 # The first trick is to build b2j ignoring the possibility
2025-07-02 04:52:34.079 # of junk. I.e., we don't call isjunk at all yet. Throwing
2025-07-02 04:52:34.079 # out the junk later is much cheaper than building b2j "right"
2025-07-02 04:52:34.079 # from the start.
2025-07-02 04:52:34.079 b = self.b
2025-07-02 04:52:34.079 self.b2j = b2j = {}
2025-07-02 04:52:34.079
2025-07-02 04:52:34.079 for i, elt in enumerate(b):
2025-07-02 04:52:34.079 indices = b2j.setdefault(elt, [])
2025-07-02 04:52:34.079 indices.append(i)
2025-07-02 04:52:34.079
2025-07-02 04:52:34.079 # Purge junk elements
2025-07-02 04:52:34.079 self.bjunk = junk = set()
2025-07-02 04:52:34.079 isjunk = self.isjunk
2025-07-02 04:52:34.079 if isjunk:
2025-07-02 04:52:34.079 > for elt in b2j.keys():
2025-07-02 04:52:34.079 E RecursionError: maximum recursion depth exceeded while calling a Python object
2025-07-02 04:52:34.079
2025-07-02 04:52:34.079 C:\Python3x\Lib\difflib.py:288: RecursionError
2025-07-02 04:52:34.079 ---------------------------- Captured stdout setup ----------------------------
2025-07-02 04:52:34.079 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 0x0000025DB66BDC60>, 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
|