Check firebird.log [no messages found for interval when this test was running]
Jump to: output_first_mismatch    outcomes_full_history    elapsed_time_chart
Show cross-report outcomes.

Annotation type Annotation details
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
Full history of outcomes and elapsed time, ms:
NN SNAP_INFO CS_outcome SS_outcome CS_run_time SS_run_time CS_run_beg CS_run_end SS_run_beg SS_run_end
1 6.0.0.892 2025.07.03 af84a P P 608 423 2025.07.03 20:42:09.592 2025.07.03 20:42:10.200 2025.07.03 19:05:12.950 2025.07.03 19:05:13.373
2 6.0.0.892 2025.07.02 10f7d P P 688 412 2025.07.03 02:04:14.732 2025.07.03 02:04:15.420 2025.07.03 00:25:40.144 2025.07.03 00:25:40.556
3 6.0.0.889 2025.07.02 4b4e6 P P 646 410 2025.07.02 10:02:21.916 2025.07.02 10:02:22.562 2025.07.02 08:26:49.037 2025.07.02 08:26:49.447
4 6.0.0.889 2025.07.01 969ac F F 169816 172470 2025.07.02 02:05:21.084 2025.07.02 02:08:10.900 2025.07.02 00:25:24.449 2025.07.02 00:28:16.919
5 6.0.0.881 2025.06.27 7035d P P 624 412 2025.07.01 02:02:09.754 2025.07.01 02:02:10.378 2025.07.01 00:25:34.137 2025.07.01 00:25:34.549
6 6.0.0.877 2025.06.26 8e38f P P 624 437 2025.06.27 02:02:48.597 2025.06.27 02:02:49.221 2025.06.27 00:25:27.126 2025.06.27 00:25:27.563
7 6.0.0.876 2025.06.25 b1bec P P 617 433 2025.06.26 02:08:07.688 2025.06.26 02:08:08.305 2025.06.26 00:30:40.954 2025.06.26 00:30:41.387
8 6.0.0.863 2025.06.24 c3c20 P P 596 604 2025.06.25 06:52:25.902 2025.06.25 06:52:26.498 2025.06.25 00:25:24.440 2025.06.25 00:25:25.044
9 6.0.0.858 2025.06.24 cbbbf P P 616 444 2025.06.24 16:34:28.203 2025.06.24 16:34:28.819 2025.06.24 14:57:22.939 2025.06.24 14:57:23.383
10 6.0.0.858 2025.06.23 d377c P P 615 412 2025.06.24 07:46:23.348 2025.06.24 07:46:23.963 2025.06.24 06:09:51.788 2025.06.24 06:09:52.200
11 6.0.0.854 2025.06.23 10b58 P P 648 398 2025.06.23 14:27:06.545 2025.06.23 14:27:07.193 2025.06.23 12:49:09.998 2025.06.23 12:49:10.396
12 6.0.0.849 2025.06.20 7b79c P P 681 397 2025.06.21 02:06:14.472 2025.06.21 02:06:15.153 2025.06.21 00:25:44.939 2025.06.21 00:25:45.336
13 6.0.0.848 2025.06.19 c483c P P 635 410 2025.06.20 02:05:43.498 2025.06.20 02:05:44.133 2025.06.20 00:25:32.951 2025.06.20 00:25:33.361
14 6.0.0.845 2025.06.18 20191 P P 636 414 2025.06.19 02:05:24.636 2025.06.19 02:05:25.272 2025.06.19 00:25:33.676 2025.06.19 00:25:34.090
15 6.0.0.843 2025.06.16 995f4 P P 616 432 2025.06.18 02:05:08.567 2025.06.18 02:05:09.183 2025.06.18 00:25:33.710 2025.06.18 00:25:34.142
16 6.0.0.840 2025.06.14 29bca P P 683 556 2025.06.15 02:12:02.677 2025.06.15 02:12:03.360 2025.06.15 00:27:10.837 2025.06.15 00:27:11.393
17 6.0.0.838 2025.06.13 0e28a P P 699 418 2025.06.14 02:10:33.758 2025.06.14 02:10:34.457 2025.06.14 00:25:56.323 2025.06.14 00:25:56.741
18 6.0.0.834 2025.06.11 e889f P P 696 401 2025.06.12 02:08:35.868 2025.06.12 02:08:36.564 2025.06.12 00:26:08.589 2025.06.12 00:26:08.990
19 6.0.0.800 2025.06.10 1f226 P P 661 397 2025.06.11 01:25:22.273 2025.06.11 01:25:22.934 2025.06.11 00:23:31.345 2025.06.11 00:23:31.742
20 6.0.0.799 2025.06.07 be644 P P 580 382 2025.06.10 01:24:52.113 2025.06.10 01:24:52.693 2025.06.10 00:23:22.637 2025.06.10 00:23:23.019
21 6.0.0.797 2025.06.06 303e8 P P 639 365 2025.06.07 01:24:08.972 2025.06.07 01:24:09.611 2025.06.07 00:23:20.682 2025.06.07 00:23:21.047
22 6.0.0.795 2025.05.29 7a71a P P 586 393 2025.06.06 01:24:00.803 2025.06.06 01:24:01.389 2025.06.06 00:23:21.913 2025.06.06 00:23:22.306
23 6.0.0.792 2025.05.28 ee5a8 P P 585 367 2025.05.29 01:23:12.048 2025.05.29 01:23:12.633 2025.05.29 00:23:18.631 2025.05.29 00:23:18.998
24 6.0.0.791 2025.05.27 02db8 P P 568 380 2025.05.28 01:23:12.059 2025.05.28 01:23:12.627 2025.05.28 00:23:17.201 2025.05.28 00:23:17.581
25 6.0.0.789 2025.05.21 64051 P P 562 400 2025.05.25 01:23:23.181 2025.05.25 01:23:23.743 2025.05.25 00:23:23.533 2025.05.25 00:23:23.933
26 6.0.0.787 2025.05.20 230ad P P 597 367 2025.05.21 01:22:13.260 2025.05.21 01:22:13.857 2025.05.21 00:23:12.015 2025.05.21 00:23:12.382
27 6.0.0.783 2025.05.12 37320 P P 558 369 2025.05.19 01:22:24.126 2025.05.19 01:22:24.684 2025.05.19 00:23:15.865 2025.05.19 00:23:16.234
28 6.0.0.779 2025.05.11 136fa P P 625 383 2025.05.12 01:23:51.149 2025.05.12 01:23:51.774 2025.05.12 00:23:25.717 2025.05.12 00:23:26.100
29 6.0.0.778 2025.05.07 d735e P P 574 379 2025.05.11 01:23:33.346 2025.05.11 01:23:33.920 2025.05.11 00:23:22.485 2025.05.11 00:23:22.864
30 6.0.0.776 2025.05.06 007cd P P 563 378 2025.05.07 01:22:45.749 2025.05.07 01:22:46.312 2025.05.07 00:23:20.373 2025.05.07 00:23:20.751
31 6.0.0.770 2025.05.05 82c4a P P 577 369 2025.05.06 01:23:23.596 2025.05.06 01:23:24.173 2025.05.06 00:23:25.590 2025.05.06 00:23:25.959
32 6.0.0.767 2025.05.01 cdd29 P P 590 382 2025.05.02 01:23:54.507 2025.05.02 01:23:55.097 2025.05.02 00:23:33.950 2025.05.02 00:23:34.332
33 6.0.0.762 2025.04.30 5cb15 P P 596 365 2025.05.01 01:22:46.819 2025.05.01 01:22:47.415 2025.05.01 00:23:34.481 2025.05.01 00:23:34.846
34 6.0.0.755 2025.04.29 739c6 P P 558 382 2025.04.30 01:22:39.563 2025.04.30 01:22:40.121 2025.04.30 00:23:20.774 2025.04.30 00:23:21.156
35 6.0.0.753 2025.04.27 29ab3 P P 559 396 2025.04.29 01:22:51.738 2025.04.29 01:22:52.297 2025.04.29 00:23:34.396 2025.04.29 00:23:34.792
36 6.0.0.745 2025.04.21 78ad8 P P 569 378 2025.04.26 01:23:38.727 2025.04.26 01:23:39.296 2025.04.26 00:23:20.001 2025.04.26 00:23:20.379
37 6.0.0.744 2025.04.19 e883a P P 571 377 2025.04.20 01:23:09.974 2025.04.20 01:23:10.545 2025.04.20 00:23:27.425 2025.04.20 00:23:27.802
38 6.0.0.742 2025.04.17 abc3b P P 563 380 2025.04.19 01:22:49.607 2025.04.19 01:22:50.170 2025.04.19 00:23:15.825 2025.04.19 00:23:16.205
39 6.0.0.737 2025.04.16 fe52b P P 594 401 2025.04.17 01:23:33.743 2025.04.17 01:23:34.337 2025.04.17 00:23:16.942 2025.04.17 00:23:17.343
40 6.0.0.736 2025.04.14 3e6be P P 592 393 2025.04.15 01:23:28.712 2025.04.15 01:23:29.304 2025.04.15 00:23:25.701 2025.04.15 00:23:26.094
41 6.0.0.735 2025.04.13 6635c P P 567 392 2025.04.14 01:23:31.374 2025.04.14 01:23:31.941 2025.04.14 00:23:15.803 2025.04.14 00:23:16.195
42 6.0.0.734 2025.04.12 e2fd1 P P 547 391 2025.04.13 01:21:47.852 2025.04.13 01:21:48.399 2025.04.13 00:23:29.914 2025.04.13 00:23:30.305
43 6.0.0.730 2025.04.11 240b8 P P 641 438 2025.04.12 01:27:09.364 2025.04.12 01:27:10.005 2025.04.12 00:23:41.407 2025.04.12 00:23:41.845
44 6.0.0.726 2025.04.10 d79c6 P P 686 388 2025.04.11 01:26:58.922 2025.04.11 01:26:59.608 2025.04.11 00:23:50.868 2025.04.11 00:23:51.256
45 6.0.0.725 2025.04.09 a2b05 P P 677 428 2025.04.10 01:26:57.288 2025.04.10 01:26:57.965 2025.04.10 00:23:39.060 2025.04.10 00:23:39.488
46 6.0.0.722 2025.04.08 a8b86 P P 602 400 2025.04.09 01:23:12.227 2025.04.09 01:23:12.829 2025.04.09 00:23:23.844 2025.04.09 00:23:24.244
47 6.0.0.719 2025.04.06 90fd9 P P 569 386 2025.04.08 01:23:36.970 2025.04.08 01:23:37.539 2025.04.08 00:23:19.176 2025.04.08 00:23:19.562
48 6.0.0.717 2025.04.04 53d70 P P 587 398 2025.04.05 01:23:37.089 2025.04.05 01:23:37.676 2025.04.05 00:23:23.441 2025.04.05 00:23:23.839
49 6.0.0.716 2025.04.03 fc636 P P 571 383 2025.04.04 01:23:37.751 2025.04.04 01:23:38.322 2025.04.04 00:23:23.727 2025.04.04 00:23:24.110
50 6.0.0.715 2025.04.02 907ed P P 575 382 2025.04.03 01:23:35.121 2025.04.03 01:23:35.696 2025.04.03 00:23:19.200 2025.04.03 00:23:19.582
51 6.0.0.710 2025.04.01 40651 P P 577 826 2025.04.02 01:23:52.970 2025.04.02 01:23:53.547 2025.04.02 00:23:31.802 2025.04.02 00:23:32.628
52 6.0.0.708 2025.03.31 cb069 P P 590 379 2025.04.01 01:23:07.687 2025.04.01 01:23:08.277 2025.04.01 00:23:19.927 2025.04.01 00:23:20.306
53 6.0.0.707 2025.03.28 4bd4f P P 584 408 2025.03.31 01:23:07.790 2025.03.31 01:23:08.374 2025.03.31 00:23:19.824 2025.03.31 00:23:20.232
54 6.0.0.702 2025.03.27 86f4d P P 616 384 2025.03.28 01:39:57.058 2025.03.28 01:39:57.674 2025.03.28 00:23:43.550 2025.03.28 00:23:43.934
55 6.0.0.698 2025.03.26 d72a7 P P 638 523 2025.03.27 15:05:23.592 2025.03.27 15:05:24.230 2025.03.27 14:03:14.726 2025.03.27 14:03:15.249
56 6.0.0.693 2025.03.25 8aac2 P P 591 420 2025.03.26 01:25:50.683 2025.03.26 01:25:51.274 2025.03.26 00:23:39.465 2025.03.26 00:23:39.885
57 6.0.0.693 2025.03.24 0b559 P P 640 412 2025.03.25 01:25:51.208 2025.03.25 01:25:51.848 2025.03.25 00:23:42.847 2025.03.25 00:23:43.259
58 6.0.0.687 2025.03.22 730aa P P 613 408 2025.03.24 01:26:21.620 2025.03.24 01:26:22.233 2025.03.24 00:23:47.415 2025.03.24 00:23:47.823
59 6.0.0.686 2025.03.20 71bf6 P P 584 382 2025.03.21 01:23:47.489 2025.03.21 01:23:48.073 2025.03.21 00:23:21.650 2025.03.21 00:23:22.032
60 6.0.0.685 2025.03.19 a8577 P P 604 401 2025.03.20 01:24:07.950 2025.03.20 01:24:08.554 2025.03.20 00:23:40.349 2025.03.20 00:23:40.750
61 6.0.0.680 2025.03.18 90d29 P P 584 385 2025.03.19 01:24:19.366 2025.03.19 01:24:19.950 2025.03.19 00:23:42.253 2025.03.19 00:23:42.638
62 6.0.0.677 2025.03.16 c0a60 P P 576 388 2025.03.18 01:22:35.569 2025.03.18 01:22:36.145 2025.03.18 00:23:24.185 2025.03.18 00:23:24.573
63 6.0.0.676 2025.03.15 11cfb P P 565 379 2025.03.16 01:21:34.931 2025.03.16 01:21:35.496 2025.03.16 00:23:15.551 2025.03.16 00:23:15.930
64 6.0.0.674 2025.03.14 7d82c P P 593 396 2025.03.15 01:20:38.057 2025.03.15 01:20:38.650 2025.03.15 00:23:13.720 2025.03.15 00:23:14.116
65 6.0.0.673 2025.03.13 40f5b P P 593 375 2025.03.14 13:51:57.662 2025.03.14 13:51:58.255 2025.03.14 12:53:22.478 2025.03.14 12:53:22.853
66 6.0.0.671 2025.03.12 a4fff P P 691 406 2025.03.13 01:24:53.880 2025.03.13 01:24:54.571 2025.03.13 00:23:57.226 2025.03.13 00:23:57.632
67 6.0.0.663 2025.03.11 65970 P P 665 407 2025.03.12 01:24:38.161 2025.03.12 01:24:38.826 2025.03.12 00:23:55.238 2025.03.12 00:23:55.645
68 6.0.0.661 2025.03.07 b9869 P P 636 442 2025.03.11 01:24:36.198 2025.03.11 01:24:36.834 2025.03.11 00:23:38.035 2025.03.11 00:23:38.477
69 6.0.0.660 2025.03.04 a6700 P P 606 419 2025.03.06 01:24:19.575 2025.03.06 01:24:20.181 2025.03.06 00:23:41.424 2025.03.06 00:23:41.843
70 6.0.0.658 2025.03.03 f15f8 P P 629 414 2025.03.04 01:22:46.610 2025.03.04 01:22:47.239 2025.03.04 00:23:30.348 2025.03.04 00:23:30.762
71 6.0.0.656 2025.02.27 25fb4 P P 609 381 2025.03.03 01:22:58.137 2025.03.03 01:22:58.746 2025.03.03 00:23:46.161 2025.03.03 00:23:46.542
72 6.0.0.655 2025.02.25 6e3e0 P P 598 386 2025.02.27 01:23:29.667 2025.02.27 01:23:30.265 2025.02.27 00:23:37.558 2025.02.27 00:23:37.944
73 6.0.0.654 2025.02.24 b7141 P P 616 381 2025.02.25 01:21:39.666 2025.02.25 01:21:40.282 2025.02.25 00:23:33.930 2025.02.25 00:23:34.311
74 6.0.0.652 2025.02.22 22662 P P 593 388 2025.02.24 01:20:45.506 2025.02.24 01:20:46.099 2025.02.24 00:23:14.597 2025.02.24 00:23:14.985
75 6.0.0.647 2025.02.21 9fccb P P 563 397 2025.02.22 01:20:14.836 2025.02.22 01:20:15.399 2025.02.22 00:23:07.045 2025.02.22 00:23:07.442
76 6.0.0.640 2025.02.19 9b8ac P P 569 385 2025.02.20 01:20:48.207 2025.02.20 01:20:48.776 2025.02.20 00:23:17.957 2025.02.20 00:23:18.342
77 6.0.0.639 2025.02.18 201a4 P P 567 394 2025.02.19 01:21:46.521 2025.02.19 01:21:47.088 2025.02.19 00:23:45.751 2025.02.19 00:23:46.145
78 6.0.0.637 2025.02.12 6d0f5 P P 640 391 2025.02.14 01:22:42.012 2025.02.14 01:22:42.652 2025.02.14 00:23:52.452 2025.02.14 00:23:52.843
79 6.0.0.636 2025.02.11 0424f P P 617 391 2025.02.12 01:21:56.963 2025.02.12 01:21:57.580 2025.02.12 00:23:26.562 2025.02.12 00:23:26.953
80 6.0.0.635 2025.02.10 f640f P P 567 397 2025.02.11 01:21:22.997 2025.02.11 01:21:23.564 2025.02.11 00:23:16.893 2025.02.11 00:23:17.290
81 6.0.0.629 2025.02.07 194f9 P P 611 376 2025.02.08 01:21:21.380 2025.02.08 01:21:21.991 2025.02.08 00:23:19.526 2025.02.08 00:23:19.902
82 6.0.0.628 2025.02.06 859d5 P P 576 381 2025.02.07 10:18:45.895 2025.02.07 10:18:46.471 2025.02.07 09:14:14.195 2025.02.07 09:14:14.576
83 6.0.0.621 2025.02.05 34fe7 P P 582 387 2025.02.07 01:28:42.739 2025.02.07 01:28:43.321 2025.02.07 00:23:23.492 2025.02.07 00:23:23.879
84 6.0.0.609 2025.02.04 76d57 P P 568 410 2025.02.05 01:28:29.387 2025.02.05 01:28:29.955 2025.02.05 00:23:37.450 2025.02.05 00:23:37.860
85 6.0.0.607 2025.02.03 1985b P P 596 389 2025.02.04 01:28:17.797 2025.02.04 01:28:18.393 2025.02.04 00:23:21.256 2025.02.04 00:23:21.645
86 6.0.0.601 2025.02.01 6af07 P P 576 379 2025.02.02 01:21:26.974 2025.02.02 01:21:27.550 2025.02.02 00:23:27.593 2025.02.02 00:23:27.972
87 6.0.0.600 2025.01.27 188de P P 618 384 2025.01.28 01:21:20.479 2025.01.28 01:21:21.097 2025.01.28 00:23:13.383 2025.01.28 00:23:13.767
88 6.0.0.599 2025.01.25 ba588 P P 576 393 2025.01.26 01:21:00.843 2025.01.26 01:21:01.419 2025.01.26 00:23:12.492 2025.01.26 00:23:12.885
89 6.0.0.598 2025.01.23 ddbc3 P P 568 380 2025.01.25 11:09:19.137 2025.01.25 11:09:19.705 2025.01.25 10:10:51.082 2025.01.25 10:10:51.462
90 6.0.0.595 2025.01.22 e62f3 P P 573 394 2025.01.23 01:21:09.699 2025.01.23 01:21:10.272 2025.01.23 00:23:13.349 2025.01.23 00:23:13.743
91 6.0.0.594 2025.01.21 47fb6 P P 568 379 2025.01.22 01:21:03.794 2025.01.22 01:21:04.362 2025.01.22 00:23:11.130 2025.01.22 00:23:11.509
92 6.0.0.590 2025.01.20 3d7c0 P P 599 377 2025.01.21 01:21:19.698 2025.01.21 01:21:20.297 2025.01.21 00:23:12.376 2025.01.21 00:23:12.753
93 6.0.0.588 2025.01.19 b1c4e P P 562 379 2025.01.20 01:20:46.346 2025.01.20 01:20:46.908 2025.01.20 00:23:20.356 2025.01.20 00:23:20.735
94 6.0.0.587 2025.01.18 63e6e P P 594 375 2025.01.19 01:20:31.541 2025.01.19 01:20:32.135 2025.01.19 00:23:06.909 2025.01.19 00:23:07.284
95 6.0.0.585 2025.01.16 2d6bb P P 563 406 2025.01.18 01:20:29.157 2025.01.18 01:20:29.720 2025.01.18 00:23:43.108 2025.01.18 00:23:43.514
96 6.0.0.584 2025.01.15 a0aa2 P P 573 693 2025.01.16 01:22:06.258 2025.01.16 01:22:06.831 2025.01.16 00:23:24.430 2025.01.16 00:23:25.123
97 6.0.0.581 2025.01.15 69690 P P 603 394 2025.01.15 17:31:37.312 2025.01.15 17:31:37.915 2025.01.15 16:32:57.326 2025.01.15 16:32:57.720
98 6.0.0.581 2025.01.14 21e9e P P 657 386 2025.01.15 01:22:11.258 2025.01.15 01:22:11.915 2025.01.15 00:23:21.137 2025.01.15 00:23:21.523
99 6.0.0.577 2025.01.14 91dce P P 582 394 2025.01.14 16:42:54.439 2025.01.14 16:42:55.021 2025.01.14 15:44:42.991 2025.01.14 15:44:43.385
100 6.0.0.577 2025.01.13 7e293 P P 568 407 2025.01.14 11:05:55.730 2025.01.14 11:05:56.298 2025.01.14 10:08:05.685 2025.01.14 10:08:06.092
101 6.0.0.576 2025.01.12 05898 P P 657 391 2025.01.13 01:22:36.189 2025.01.13 01:22:36.846 2025.01.13 00:23:44.618 2025.01.13 00:23:45.009
102 6.0.0.573 2025.01.10 c20f3 P P 654 562 2025.01.11 01:22:34.853 2025.01.11 01:22:35.507 2025.01.11 00:23:49.047 2025.01.11 00:23:49.609
103 6.0.0.571 2024.12.31 81bba P P 595 379 2025.01.01 01:21:39.552 2025.01.01 01:21:40.147 2025.01.01 00:23:23.726 2025.01.01 00:23:24.105
104 6.0.0.570 2024.12.30 c3c8d P P 629 392 2024.12.31 01:22:04.441 2024.12.31 01:22:05.070 2024.12.31 00:23:44.257 2024.12.31 00:23:44.649
105 6.0.0.565 2024.12.28 5fc59 P P 602 388 2024.12.29 17:17:12.644 2024.12.29 17:17:13.246 2024.12.29 16:19:04.430 2024.12.29 16:19:04.818
106 6.0.0.564 2024.12.26 12514 P P 591 375 2024.12.27 01:21:31.293 2024.12.27 01:21:31.884 2024.12.27 00:23:28.482 2024.12.27 00:23:28.857
107 6.0.0.560 2024.12.25 fa83e P P 571 396 2024.12.26 01:21:34.719 2024.12.26 01:21:35.290 2024.12.26 00:23:18.612 2024.12.26 00:23:19.008
108 6.0.0.559 2024.12.23 cc800 P P 576 405 2024.12.25 01:21:39.476 2024.12.25 01:21:40.052 2024.12.25 00:23:23.806 2024.12.25 00:23:24.211
109 6.0.0.556 2024.12.22 a0404 P P 661 388 2024.12.23 01:21:12.352 2024.12.23 01:21:13.013 2024.12.23 00:23:29.891 2024.12.23 00:23:30.279
110 6.0.0.555 2024.12.19 6990a P P 579 391 2024.12.21 12:16:07.645 2024.12.21 12:16:08.224 2024.12.21 11:17:46.041 2024.12.21 11:17:46.432
111 6.0.0.553 2024.12.17 d1f8a P P 572 374 2024.12.18 01:21:05.624 2024.12.18 01:21:06.196 2024.12.18 00:23:48.015 2024.12.18 00:23:48.389
112 6.0.0.552 2024.12.11 85e25 P P 619 381 2024.12.16 01:20:41.295 2024.12.16 01:20:41.914 2024.12.16 00:23:25.413 2024.12.16 00:23:25.794
113 6.0.0.550 2024.12.10 b37ac P P 574 391 2024.12.11 01:21:35.721 2024.12.11 01:21:36.295 2024.12.11 00:23:26.604 2024.12.11 00:23:26.995
114 6.0.0.548 2024.12.08 2cc77 P P 640 462 2024.12.09 01:24:49.337 2024.12.09 01:24:49.977 2024.12.09 00:25:23.279 2024.12.09 00:25:23.741
115 6.0.0.544 2024.12.05 96943 P P 669 456 2024.12.06 01:20:48.121 2024.12.06 01:20:48.790 2024.12.06 00:23:53.730 2024.12.06 00:23:54.186
116 6.0.0.543 2024.12.03 30b77 P P 637 397 2024.12.04 01:21:00.945 2024.12.04 01:21:01.582 2024.12.04 00:23:42.076 2024.12.04 00:23:42.473
117 6.0.0.540 2024.12.02 4a1f4 P P 665 393 2024.12.03 01:20:30.116 2024.12.03 01:20:30.781 2024.12.03 00:23:57.044 2024.12.03 00:23:57.437
118 6.0.0.539 2024.11.28 1f283 P P 640 386 2024.11.30 01:19:55.155 2024.11.30 01:19:55.795 2024.11.30 00:23:36.505 2024.11.30 00:23:36.891
119 6.0.0.535 2024.11.27 6551a P P 583 390 2024.11.28 01:18:44.733 2024.11.28 01:18:45.316 2024.11.28 00:23:13.126 2024.11.28 00:23:13.516
120 6.0.0.535 2024.11.26 77b95 P P 620 389 2024.11.27 01:19:05.132 2024.11.27 01:19:05.752 2024.11.27 00:23:04.589 2024.11.27 00:23:04.978
121 6.0.0.534 2024.11.25 e9584 P P 578 376 2024.11.26 01:19:10.459 2024.11.26 01:19:11.037 2024.11.26 00:23:13.662 2024.11.26 00:23:14.038
122 6.0.0.533 2024.11.17 933ac P P 571 381 2024.11.22 01:19:21.745 2024.11.22 01:19:22.316 2024.11.22 00:23:14.504 2024.11.22 00:23:14.885
123 6.0.0.532 2024.11.17 1a471 P P 573 393 2024.11.17 13:53:37.694 2024.11.17 13:53:38.267 2024.11.17 12:58:07.867 2024.11.17 12:58:08.260
124 6.0.0.532 2024.11.16 9e263 P P 574 376 2024.11.17 01:18:11.104 2024.11.17 01:18:11.678 2024.11.17 00:23:06.087 2024.11.17 00:23:06.463
125 6.0.0.530 2024.11.15 49804 P P 563 411 2024.11.16 01:17:43.041 2024.11.16 01:17:43.604 2024.11.16 00:23:27.583 2024.11.16 00:23:27.994
126 6.0.0.528 2024.11.14 9625b P P 633 385 2024.11.15 01:20:24.345 2024.11.15 01:20:24.978 2024.11.15 00:23:29.096 2024.11.15 00:23:29.481
127 6.0.0.526 2024.11.12 65b80 P P 667 384 2024.11.14 01:20:00.094 2024.11.14 01:20:00.761 2024.11.14 00:23:22.514 2024.11.14 00:23:22.898
128 6.0.0.523 2024.11.08 8ca23 P P 573 379 2024.11.11 01:18:40.797 2024.11.11 01:18:41.370 2024.11.11 00:23:17.668 2024.11.11 00:23:18.047
129 6.0.0.520 2024.11.08 52657 P P 562 376 2024.11.08 17:53:06.546 2024.11.08 17:53:07.108 2024.11.08 16:58:24.583 2024.11.08 16:58:24.959
130 6.0.0.520 2024.11.07 4eefa P P 566 418 2024.11.08 01:17:32.627 2024.11.08 01:17:33.193 2024.11.08 00:23:10.871 2024.11.08 00:23:11.289
131 6.0.0.516 2024.11.04 b0c36 P P 607 401 2024.11.05 01:18:42.681 2024.11.05 01:18:43.288 2024.11.05 00:23:02.906 2024.11.05 00:23:03.307
132 6.0.0.515 2024.10.30 d53f3 P P 569 409 2024.11.04 01:18:30.704 2024.11.04 01:18:31.273 2024.11.04 00:23:20.138 2024.11.04 00:23:20.547
133 6.0.0.512 2024.10.29 833ef P P 657 402 2024.10.30 01:20:14.297 2024.10.30 01:20:14.954 2024.10.30 00:23:32.270 2024.10.30 00:23:32.672
134 6.0.0.511 2024.10.26 c4bc9 P P 637 457 2024.10.29 01:19:42.774 2024.10.29 01:19:43.411 2024.10.29 00:23:12.352 2024.10.29 00:23:12.809
135 6.0.0.508 2024.10.24 a8f5b P P 658 395 2024.10.26 09:26:39.491 2024.10.26 09:26:40.149 2024.10.26 08:29:55.641 2024.10.26 08:29:56.036
136 6.0.0.502 2024.10.22 6bfd7 P P 596 389 2024.10.23 01:19:18.894 2024.10.23 01:19:19.490 2024.10.23 00:23:17.736 2024.10.23 00:23:18.125
137 6.0.0.500 2024.10.21 be565 P P 656 390 2024.10.22 01:19:46.844 2024.10.22 01:19:47.500 2024.10.22 00:23:22.726 2024.10.22 00:23:23.116
138 6.0.0.499 2024.10.19 6214b P P 596 392 2024.10.20 01:19:10.453 2024.10.20 01:19:11.049 2024.10.20 00:23:03.263 2024.10.20 00:23:03.655
139 6.0.0.498 2024.10.18 591a7 P P 579 400 2024.10.19 01:18:43.071 2024.10.19 01:18:43.650 2024.10.19 00:23:07.666 2024.10.19 00:23:08.066
140 6.0.0.494 2024.10.17 042ce P P 583 398 2024.10.18 01:19:13.822 2024.10.18 01:19:14.405 2024.10.18 00:23:10.566 2024.10.18 00:23:10.964
141 6.0.0.491 2024.10.14 dc5fb P P 590 385 2024.10.15 01:18:39.447 2024.10.15 01:18:40.037 2024.10.15 00:23:07.830 2024.10.15 00:23:08.215
142 6.0.0.489 2024.10.11 2ba59 P P 580 421 2024.10.12 01:18:15.920 2024.10.12 01:18:16.500 2024.10.12 00:23:04.082 2024.10.12 00:23:04.503
143 6.0.0.488 2024.10.09 1c93e P P 600 386 2024.10.10 01:18:35.064 2024.10.10 01:18:35.664 2024.10.10 00:23:11.462 2024.10.10 00:23:11.848
144 6.0.0.487 2024.10.06 065a3 P P 631 414 2024.10.07 01:19:48.645 2024.10.07 01:19:49.276 2024.10.07 00:23:25.795 2024.10.07 00:23:26.209
145 6.0.0.485 2024.10.05 9f5f7 P P 661 424 2024.10.06 01:19:36.995 2024.10.06 01:19:37.656 2024.10.06 00:23:33.801 2024.10.06 00:23:34.225
146 6.0.0.485 2024.10.04 e95c1 P P 640 388 2024.10.05 01:19:04.463 2024.10.05 01:19:05.103 2024.10.05 00:23:16.015 2024.10.05 00:23:16.403
147 6.0.0.483 2024.10.02 5e5ae P P 634 441 2024.10.03 01:20:03.355 2024.10.03 01:20:03.989 2024.10.03 00:23:38.046 2024.10.03 00:23:38.487
148 6.0.0.478 2024.09.30 b5010 P P 757 394 2024.10.01 01:19:22.922 2024.10.01 01:19:23.679 2024.10.01 00:23:17.519 2024.10.01 00:23:17.913
149 6.0.0.474 2024.09.26 e4efb P P 669 399 2024.09.30 01:19:03.937 2024.09.30 01:19:04.606 2024.09.30 00:23:25.821 2024.09.30 00:23:26.220
150 6.0.0.471 2024.09.25 dab71 P P 631 451 2024.09.26 01:19:30.272 2024.09.26 01:19:30.903 2024.09.26 00:23:27.367 2024.09.26 00:23:27.818
151 6.0.0.471 2024.09.24 01b51 P P 622 388 2024.09.25 01:20:15.158 2024.09.25 01:20:15.780 2024.09.25 00:23:30.548 2024.09.25 00:23:30.936
152 6.0.0.470 2024.09.23 77cc0 P P 660 416 2024.09.24 01:19:25.471 2024.09.24 01:19:26.131 2024.09.24 00:23:26.724 2024.09.24 00:23:27.140
153 6.0.0.467 2024.09.21 ea0b8 P P 645 415 2024.09.23 01:20:32.486 2024.09.23 01:20:33.131 2024.09.23 00:23:47.396 2024.09.23 00:23:47.811
154 6.0.0.466 2024.09.20 32dc6 P P 627 629 2024.09.21 01:19:00.948 2024.09.21 01:19:01.575 2024.09.21 00:23:23.639 2024.09.21 00:23:24.268
155 6.0.0.461 2024.09.17 2c895 P P 573 393 2024.09.18 01:18:01.362 2024.09.18 01:18:01.935 2024.09.18 00:23:03.614 2024.09.18 00:23:04.007
156 6.0.0.460 2024.09.11 3c253 P P 603 379 2024.09.17 01:18:18.164 2024.09.17 01:18:18.767 2024.09.17 00:23:03.010 2024.09.17 00:23:03.389
157 6.0.0.457 2024.09.09 fdc6f P P 639 393 2024.09.10 01:19:01.426 2024.09.10 01:19:02.065 2024.09.10 00:23:15.897 2024.09.10 00:23:16.290
158 6.0.0.455 2024.09.07 500d8 P P 658 408 2024.09.08 01:19:24.845 2024.09.08 01:19:25.503 2024.09.08 00:23:37.632 2024.09.08 00:23:38.040
159 6.0.0.454 2024.09.05 4d70f P P 638 446 2024.09.06 01:19:32.273 2024.09.06 01:19:32.911 2024.09.06 00:23:17.518 2024.09.06 00:23:17.964
160 6.0.0.452 2024.09.04 9ff9c P P 659 391 2024.09.05 01:19:02.882 2024.09.05 01:19:03.541 2024.09.05 00:23:20.209 2024.09.05 00:23:20.600
161 6.0.0.450 2024.09.02 27124 P P 654 389 2024.09.04 01:19:35.496 2024.09.04 01:19:36.150 2024.09.04 00:23:23.937 2024.09.04 00:23:24.326
162 6.0.0.447 2024.09.01 901b4 P P 672 394 2024.09.02 01:09:05.849 2024.09.02 01:09:06.521 2024.09.02 00:13:20.845 2024.09.02 00:13:21.239
163 6.0.0.446 2024.08.30 fe1b2 P P 640 396 2024.09.01 01:07:47.312 2024.09.01 01:07:47.952 2024.09.01 00:13:18.451 2024.09.01 00:13:18.847
164 6.0.0.444 2024.08.28 785d4 P P 671 385 2024.08.30 01:08:03.546 2024.08.30 01:08:04.217 2024.08.30 00:13:34.122 2024.08.30 00:13:34.507
165 6.0.0.442 2024.08.21 4a68f P P 651 384 2024.08.28 01:07:51.887 2024.08.28 01:07:52.538 2024.08.28 00:13:27.616 2024.08.28 00:13:28.000
166 6.0.0.441 2024.08.20 75042 P P 583 380 2024.08.21 01:06:41.355 2024.08.21 01:06:41.938 2024.08.21 00:13:16.320 2024.08.21 00:13:16.700
167 6.0.0.438 2024.08.16 088b5 P P 734 416 2024.08.19 01:08:31.003 2024.08.19 01:08:31.737 2024.08.19 00:13:16.092 2024.08.19 00:13:16.508
168 6.0.0.437 2024.08.14 3c88b P P 863 433 2024.08.16 01:10:27.569 2024.08.16 01:10:28.432 2024.08.16 00:13:39.711 2024.08.16 00:13:40.144
169 6.0.0.436 2024.08.13 b8e75 P P 776 438 2024.08.14 01:09:40.956 2024.08.14 01:09:41.732 2024.08.14 00:13:40.646 2024.08.14 00:13:41.084
170 6.0.0.432 2024.08.11 e82ac P P 642 426 2024.08.13 01:08:47.474 2024.08.13 01:08:48.116 2024.08.13 00:13:19.355 2024.08.13 00:13:19.781
171 6.0.0.431 2024.08.11 16bb1 P P 655 428 2024.08.11 17:13:54.464 2024.08.11 17:13:55.119 2024.08.11 16:18:24.599 2024.08.11 16:18:25.027
172 6.0.0.431 2024.08.09 de5a7 P P 715 448 2024.08.10 16:47:35.230 2024.08.10 16:47:35.945 2024.08.10 15:52:36.747 2024.08.10 15:52:37.195
173 6.0.0.428 2024.08.08 9191b P P 715 418 2024.08.10 01:08:09.253 2024.08.10 01:08:09.968 2024.08.10 00:13:13.854 2024.08.10 00:13:14.272
174 6.0.0.423 2024.08.07 33b41 P P 690 425 2024.08.08 08:07:25.767 2024.08.08 08:07:26.457 2024.08.08 07:12:38.087 2024.08.08 07:12:38.512
175 6.0.0.421 2024.08.06 ed60d P P 544 317 2024.08.07 01:05:50.819 2024.08.07 01:05:51.363 2024.08.07 00:12:48.135 2024.08.07 00:12:48.452
176 6.0.0.419 2024.08.05 3505a P P 517 320 2024.08.06 01:04:29.229 2024.08.06 01:04:29.746 2024.08.06 00:13:10.822 2024.08.06 00:13:11.142
177 6.0.0.409 2024.08.02 ec18f P P 602 336 2024.08.05 01:03:32.925 2024.08.05 01:03:33.527 2024.08.05 00:12:39.941 2024.08.05 00:12:40.277
178 6.0.0.406 2024.08.01 b20be P P 529 337 2024.08.02 01:02:31.364 2024.08.02 01:02:31.893 2024.08.02 00:12:21.718 2024.08.02 00:12:22.055
179 6.0.0.405 2024.07.31 a62ac P P 495 451 2024.08.01 01:09:21.940 2024.08.01 01:09:22.435 2024.08.01 00:13:41.409 2024.08.01 00:13:41.860
180 6.0.0.403 2024.07.29 30f03 P P 511 326 2024.07.30 01:04:30.757 2024.07.30 01:04:31.268 2024.07.30 00:12:23.392 2024.07.30 00:12:23.718
181 6.0.0.401 2024.07.26 24e41 P P 516 313 2024.07.27 01:03:56.543 2024.07.27 01:03:57.059 2024.07.27 00:12:16.840 2024.07.27 00:12:17.153
182 6.0.0.400 2024.07.24 5bb78 P P 496 312 2024.07.25 01:04:26.552 2024.07.25 01:04:27.048 2024.07.25 00:12:19.534 2024.07.25 00:12:19.846
183 6.0.0.398 2024.07.23 85b18 P P 522 313 2024.07.24 01:27:32.190 2024.07.24 01:27:32.712 2024.07.24 00:12:18.120 2024.07.24 00:12:18.433
184 6.0.0.397 2024.07.22 c734c P P 564 317 2024.07.23 01:04:24.846 2024.07.23 01:04:25.410 2024.07.23 00:12:23.952 2024.07.23 00:12:24.269
185 6.0.0.396 2024.07.13 cf952 P P 497 325 2024.07.22 01:04:21.400 2024.07.22 01:04:21.897 2024.07.22 00:12:26.904 2024.07.22 00:12:27.229
186 6.0.0.395 2024.07.10 845f4 P P 468 296 2024.07.13 01:04:20.146 2024.07.13 01:04:20.614 2024.07.13 00:12:30.714 2024.07.13 00:12:31.010
187 6.0.0.392 2024.07.09 ea301 P P 490 348 2024.07.10 01:06:10.507 2024.07.10 01:06:10.997 2024.07.10 00:12:44.386 2024.07.10 00:12:44.734
188 6.0.0.391 2024.07.08 7d50c P P 563 353 2024.07.09 01:06:46.792 2024.07.09 01:06:47.355 2024.07.09 00:12:51.063 2024.07.09 00:12:51.416
189 6.0.0.389 2024.07.05 cc71c P P 572 346 2024.07.06 01:07:14.957 2024.07.06 01:07:15.529 2024.07.06 00:13:02.451 2024.07.06 00:13:02.797
190 6.0.0.388 2024.06.30 e5700 P P 535 348 2024.07.01 01:07:20.527 2024.07.01 01:07:21.062 2024.07.01 00:12:58.335 2024.07.01 00:12:58.683
191 6.0.0.387 2024.06.27 7c28a P P 520 372 2024.06.28 01:07:24.154 2024.06.28 01:07:24.674 2024.06.28 00:12:53.093 2024.06.28 00:12:53.465
192 6.0.0.386 2024.06.23 7c57f P P 595 336 2024.06.24 01:04:37.093 2024.06.24 01:04:37.688 2024.06.24 00:12:37.118 2024.06.24 00:12:37.454
193 6.0.0.384 2024.06.21 24d99 P P 493 347 2024.06.22 01:02:37.244 2024.06.22 01:02:37.737 2024.06.22 00:12:15.409 2024.06.22 00:12:15.756
194 6.0.0.374 2024.06.13 0097d P P 534 323 2024.06.21 17:49:21.946 2024.06.21 17:49:22.480 2024.06.21 16:59:04.811 2024.06.21 16:59:05.134
195 6.0.0.373 2024.06.09 363f0 P P 469 234 2024.06.12 23:05:59.216 2024.06.12 23:05:59.685 2024.06.12 22:21:17.234 2024.06.12 22:21:17.468
196 6.0.0.372 2024.06.08 9e7f2 P P 422 250 2024.06.09 18:34:14.236 2024.06.09 18:34:14.658 2024.06.09 17:50:14.835 2024.06.09 17:50:15.085
197 6.0.0.368 2024.06.03 25f3e P P 578 328 2024.06.15 11:25:56.386 2024.06.15 11:25:56.964 2024.06.15 10:37:31.892 2024.06.15 10:37:32.220
198 6.0.0.366 2024.05.28 8e46f P P 406 234 2024.06.10 19:28:02.450 2024.06.10 19:28:02.856 2024.06.10 18:43:53.741 2024.06.10 18:43:53.975
199 6.0.0.363 2024.05.28 95442 P P 407 250 2024.06.10 15:48:12.992 2024.06.10 15:48:13.399 2024.06.10 15:04:04.391 2024.06.10 15:04:04.641
200 6.0.0.363 2024.05.28 40d0b P P 406 235 2024.06.10 17:41:34.859 2024.06.10 17:41:35.265 2024.06.10 16:57:28.940 2024.06.10 16:57:29.175
201 6.0.0.362 2024.05.24 ecc49 P P 453 235 2024.05.24 23:05:55.861 2024.05.24 23:05:56.314 2024.05.24 22:21:21.245 2024.05.24 22:21:21.480
202 6.0.0.359 2024.05.23 9cb11 P P 438 234 2024.05.23 23:06:23.516 2024.05.23 23:06:23.954 2024.05.23 22:21:43.390 2024.05.23 22:21:43.624
203 6.0.0.358 2024.05.21 995dd P P 438 250 2024.05.22 23:06:06.258 2024.05.22 23:06:06.696 2024.05.22 22:21:21.015 2024.05.22 22:21:21.265
204 6.0.0.357 2024.05.18 bf6c4 P P 438 234 2024.05.20 23:05:48.632 2024.05.20 23:05:49.070 2024.05.20 22:21:20.335 2024.05.20 22:21:20.569
205 6.0.0.356 2024.05.17 eab06 P P 438 250 2024.05.17 23:05:55.649 2024.05.17 23:05:56.087 2024.05.17 22:21:43.101 2024.05.17 22:21:43.351
206 6.0.0.355 2024.05.16 8dd6e P P 438 219 2024.05.16 23:05:48.062 2024.05.16 23:05:48.500 2024.05.16 22:21:23.326 2024.05.16 22:21:23.545
207 6.0.0.354 2024.05.15 d3adc P P 438 235 2024.05.15 23:06:08.198 2024.05.15 23:06:08.636 2024.05.15 22:21:42.589 2024.05.15 22:21:42.824
208 6.0.0.351 2024.05.14 2e3e0 P P 453 235 2024.05.14 23:05:37.489 2024.05.14 23:05:37.942 2024.05.14 22:21:20.336 2024.05.14 22:21:20.571
209 6.0.0.348 2024.05.08 e1ec4 P P 453 234 2024.05.13 23:05:57.935 2024.05.13 23:05:58.388 2024.05.13 22:21:38.556 2024.05.13 22:21:38.790
210 6.0.0.346 2024.05.07 9d7de P P 453 250 2024.05.07 23:06:07.952 2024.05.07 23:06:08.405 2024.05.07 22:21:37.785 2024.05.07 22:21:38.035
211 6.0.0.345 2024.05.06 154a0 P P 454 250 2024.05.06 23:05:41.751 2024.05.06 23:05:42.205 2024.05.06 22:21:18.204 2024.05.06 22:21:18.454
212 6.0.0.344 2024.05.02 b49d8 P P 438 234 2024.05.02 23:05:12.377 2024.05.02 23:05:12.815 2024.05.02 22:21:11.667 2024.05.02 22:21:11.901
213 6.0.0.342 2024.04.29 e6247 P P 437 234 2024.04.29 23:05:31.684 2024.04.29 23:05:32.121 2024.04.29 22:21:33.062 2024.04.29 22:21:33.296
214 6.0.0.339 2024.04.28 0bcba P P 438 219 2024.04.28 23:05:13.951 2024.04.28 23:05:14.389 2024.04.28 22:21:12.611 2024.04.28 22:21:12.830
215 6.0.0.336 2024.04.24 7d2ac P P 453 234 2024.04.26 23:05:16.112 2024.04.26 23:05:16.565 2024.04.26 22:21:15.418 2024.04.26 22:21:15.652
216 6.0.0.333 2024.04.23 85d98 P P 438 234 2024.04.23 23:05:42.779 2024.04.23 23:05:43.217 2024.04.23 22:21:33.291 2024.04.23 22:21:33.525
217 6.0.0.328 2024.04.22 485d0 P P 438 235 2024.04.22 23:05:19.999 2024.04.22 23:05:20.437 2024.04.22 22:21:16.073 2024.04.22 22:21:16.308
218 6.0.0.327 2024.04.19 eeed9 P P 438 235 2024.04.21 23:05:45.194 2024.04.21 23:05:45.632 2024.04.21 22:21:33.808 2024.04.21 22:21:34.043
219 6.0.0.325 2024.04.18 f5930 P P 438 234 2024.04.18 23:05:22.100 2024.04.18 23:05:22.538 2024.04.18 22:21:13.108 2024.04.18 22:21:13.342
220 6.0.0.324 2024.04.17 84ac9 P P 437 234 2024.04.17 23:05:32.723 2024.04.17 23:05:33.160 2024.04.17 22:21:35.620 2024.04.17 22:21:35.854
221 6.0.0.321 2024.04.16 eba22 P P 437 235 2024.04.16 23:05:01.104 2024.04.16 23:05:01.541 2024.04.16 22:21:15.484 2024.04.16 22:21:15.719
222 6.0.0.315 2024.04.15 4e80d P P 453 234 2024.04.15 23:05:19.568 2024.04.15 23:05:20.021 2024.04.15 22:21:31.328 2024.04.15 22:21:31.562
223 6.0.0.313 2024.04.14 b6eab P P 406 234 2024.04.14 23:04:33.994 2024.04.14 23:04:34.400 2024.04.14 22:21:33.288 2024.04.14 22:21:33.522
224 6.0.0.313 2024.04.12 aaf5f P P 406 234 2024.04.12 23:04:10.325 2024.04.12 23:04:10.731 2024.04.12 22:21:12.858 2024.04.12 22:21:13.092
225 6.0.0.312 2024.04.12 ff9f0 P P 406 234 2024.04.12 09:51:17.750 2024.04.12 09:51:18.156 2024.04.12 09:08:30.658 2024.04.12 09:08:30.892
226 6.0.0.312 2024.04.04 3496c P P 375 219 2024.04.09 23:04:53.565 2024.04.09 23:04:53.940 2024.04.09 22:21:38.304 2024.04.09 22:21:38.523
227 6.0.0.310 2024.04.03 e93f6 P P 391 234 2024.04.04 09:17:20.978 2024.04.04 09:17:21.369 2024.04.04 08:37:00.764 2024.04.04 08:37:00.998
228 6.0.0.308 2024.04.03 fa979 P P 375 235 2024.04.03 16:30:50.153 2024.04.03 16:30:50.528 2024.04.03 15:50:08.924 2024.04.03 15:50:09.159
229 6.0.0.308 2024.04.02 65562 P P 375 219 2024.04.03 00:11:35.745 2024.04.03 00:11:36.120 2024.04.02 23:31:41.656 2024.04.02 23:31:41.875
230 6.0.0.305 2024.04.01 8a4f6 P P 390 218 2024.04.02 08:23:59.041 2024.04.02 08:23:59.431 2024.04.02 07:44:03.590 2024.04.02 07:44:03.808
231 6.0.0.303 2024.03.31 ecb39 P P 390 234 2024.04.01 05:51:03.864 2024.04.01 05:51:04.254 2024.04.01 05:11:07.357 2024.04.01 05:11:07.591
232 6.0.0.301 2024.03.25 69d0a P P 374 218 2024.03.28 22:28:24.312 2024.03.28 22:28:24.686 2024.03.28 21:48:30.707 2024.03.28 21:48:30.925
233 6.0.0.299 2024.03.22 b1ba8 P P 389 218 2024.03.23 23:58:11.837 2024.03.23 23:58:12.226 2024.03.23 23:17:20.760 2024.03.23 23:17:20.978
234 6.0.0.295 2024.03.22 ef66a P P 374 218 2024.03.22 12:48:58.560 2024.03.22 12:48:58.934 2024.03.22 12:08:12.916 2024.03.22 12:08:13.134
235 6.0.0.295 2024.03.21 bf5ab P P 374 217 2024.03.21 22:09:01.666 2024.03.21 22:09:02.040 2024.03.21 21:28:07.057 2024.03.21 21:28:07.274
236 6.0.0.294 2024.03.20 bd00d P P 390 218 2024.03.21 01:11:53.877 2024.03.21 01:11:54.267 2024.03.21 00:31:10.663 2024.03.21 00:31:10.881
237 6.0.0.293 2024.03.20 fb994 P P 374 218 2024.03.20 17:44:24.633 2024.03.20 17:44:25.007 2024.03.20 17:02:49.400 2024.03.20 17:02:49.618

Elapsed time, ms. Chart for last 150 runs:

Last commits information (all timestamps in UTC):